The JavaScript language An introduction
An Introduction to JavaScript
Let’s see what’s so special about JavaScript, what we can achieve with it, and which other technologies play well
with it.
JavaScript was initially created to “make web pages alive”.
The programs in this language are called scripts. They can be written right in a web page’s HTML and executed
automatically as the page loads.
Scripts are provided and executed as plain text. They don’t need special preparation or compilation to run.
In this aspect, JavaScript is very different from another language called Java.
Why JavaScript?
When JavaScript was created, it initially had another name: “LiveScript”. But Java was very popular at that
time, so it was decided that positioning a new language as a “younger brother” of Java would help.
But as it evolved, JavaScript became a fully independent language with its own specification called
ECMAScript, and now it has no relation to Java at all.
Today, JavaScript can execute not only in the browser, but also on the server, or actually on any device that has a
special program called the JavaScript engine.
The browser has an embedded engine sometimes called a “JavaScript virtual machine”.
Different engines have different “codenames”. For example:
V8 – in Chrome and Opera.
SpiderMonkey – in Firefox.
…There are other codenames like “Trident” and “Chakra” for different versions of IE, “ChakraCore” for
Microsoft Edge, “Nitro” and “SquirrelFish” for Safari, etc.
The terms above are good to remember because they are used in developer articles on the internet. We’ll use
them too. For instance, if “a feature X is supported by V8”, then it probably works in Chrome and Opera.
How do engines work?
Engines are complicated. But the basics are easy.
1. The engine (embedded if it’s a browser) reads (“parses”) the script.
2. Then it converts (“compiles”) the script to the machine language.
3. And then the machine code runs, pretty fast.
The engine applies optimizations at each step of the process. It even watches the compiled script as it
runs, analyzes the data that flows through it, and applies optimizations to the machine code based on
that knowledge. When it’s done, scripts run quite fast.
Modern JavaScript is a “safe” programming language. It does not provide low-level access to memory or CPU,
because it was initially created for browsers which do not require it.
Javascript’s capabilities greatly depend on the environment it’s running in. For instance, Node.JS supports
functions that allow JavaScript to read/write arbitrary files, perform network requests, etc.
In-browser JavaScript can do everything related to webpage manipulation, interaction with the user, and the
webserver.
For instance, in-browser JavaScript is able to:
Add new HTML to the page, change the existing content, modify styles.
React to user actions, run on mouse clicks, pointer movements, key presses.
Send requests over the network to remote servers, download and upload files (so-called AJAX and COMET
technologies).
Get and set cookies, ask questions to the visitor, show messages.
Remember the data on the client-side (“local storage”).
JavaScript’s abilities in the browser are limited for the sake of the user’s safety. The aim is to prevent an evil
webpage from accessing private information or harming the user’s data.
Examples of such restrictions include:
JavaScript on a webpage may not read/write arbitrary files on the hard disk, copy them or execute programs.
It has no direct access to OS system functions.
Modern browsers allow it to work with files, but the access is limited and only provided if the user does certain
actions, like “dropping” a file into a browser window or selecting it via an <input> tag.
There are ways to interact with camera/microphone and other devices, but they require a user’s explicit
permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings
and send the information to the NSA.
Different tabs/windows generally do not know about each other. Sometimes they do, for example when one
window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access
the other if they come from different sites (from a different domain, protocol or port).
This is called the “Same Origin Policy”. To work around that, both pages must contain a special JavaScript code
that handles data exchange.
This limitation is, again, for the user’s safety. A page from http://anysite.com which a user has opened
must not be able to access another browser tab with the URL http://gmail.com and steal information from
there.
JavaScript can easily communicate over the net to the server where the current page came from. But its ability
to receive data from other sites/domains is crippled. Though possible, it requires explicit agreement
(expressed in HTTP headers) from the remote side. Once again, that’s a safety limitation.
Such limits do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers
also allow plugin/extensions which may ask for extended permissions.
There are at least three great things about JavaScript:
Javascript is the only browser technology that combines these three things.
That’s what makes JavaScript unique. That’s why it’s the most widespread tool for creating browser interfaces.
While planning to learn a new technology, it’s beneficial to check its perspectives. So let’s move on to the
modern trends affecting it, including new languages and browser abilities.
The syntax of JavaScript does not suit everyone’s needs. Different people want different features.
That’s to be expected, because projects and requirements are different for everyone.
So recently a plethora of new languages appeared, which are transpiled (converted) to JavaScript before they run
in the browser.
Modern tools make the transpilation very fast and transparent, actually allowing developers to code in another
language and auto-converting it “under the hood”.
Examples of such languages:
CoffeeScript is a “syntactic sugar” for JavaScript. It introduces shorter syntax, allowing us to write clearer and
more precise code. Usually, Ruby devs like it.
TypeScript is concentrated on adding “strict data typing” to simplify the development and support of complex
systems. It is developed by Microsoft.
Dart is a standalone language that has its own engine that runs in non-browser environments (like mobile
apps). It was initially offered by Google as a replacement for JavaScript, but as of now, browsers require it to
be transpiled to JavaScript just like the ones above.
There are more. Of course, even if we use one of these languages, we should also know JavaScript to really
understand what we’re doing.
JavaScript was initially created as a browser-only language, but is now used in many other environments as
well.
Today, JavaScript has a unique position as the most widely-adopted browser language with full integration
with HTML/CSS.
There are many languages that get “transpiled” to JavaScript and provide certain features. It is recommended
to take a look at them, at least briefly, after mastering JavaScript.
What is JavaScript?
What can in-browser JavaScript do?
What CAN’T in-browser JavaScript do?
What makes JavaScript unique?
Full integration with HTML/CSS.
Simple things are done simply.
Support by all major browsers and enabled by default.
Languages “over” JavaScript
Summary
Comments
!
Chapter
An introduction
Lesson navigation
What is JavaScript?
What can in-browser
JavaScript do?
What CAN’T in-browser
JavaScript do?
What makes JavaScript
unique?
Languages “over” JavaScript
Summary
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language An introduction
Code editors
A code editor is the place where programmers spend most of their time.
There are two main types of code editors: IDEs and lightweight editors. Many people use one tool of each type.
The term IDE (Integrated Development Environment) refers to a powerful editor with many features that usually
operates on a “whole project.” As the name suggests, it’s not just an editor, but a full-scale “development
environment.”
An IDE loads the project (which can be many files), allows navigation between files, provides autocompletion
based on the whole project (not just the open file), and integrates with a version management system (like git), a
testing environment, and other “project-level” stuff.
If you haven’t selected an IDE yet, consider the following options:
WebStorm for frontend development. The same company offers other editors for other languages (paid).
Netbeans (free).
All of these IDEs are cross-platform.
For Windows, there’s also “Visual Studio”, not to be confused with “Visual Studio Code.” “Visual Studio” is a paid
and mighty Windows-only editor, well-suited for the .NET platform. A free version of it is called Visual Studio
Community.
Many IDEs are paid but have a trial period. Their cost is usually negligible compared to a qualified developer’s
salary, so just choose the best one for you.
“Lightweight editors” are not as powerful as IDEs, but they’re fast, elegant and simple.
They are mainly used to open and edit a file instantly.
The main difference between a “lightweight editor” and an “IDE” is that an IDE works on a project-level, so it
loads much more data on start, analyzes the project structure if needed and so on. A lightweight editor is much
faster if we need only one file.
In practice, lightweight editors may have a lot of plugins including directory-level syntax analyzers and
autocompleters, so there’s no strict border between a lightweight editor and an IDE.
The following options deserve your attention:
Visual Studio Code (cross-platform, free) also has many IDE-like features.
Atom (cross-platform, free).
Sublime Text (cross-platform, shareware).
Notepad++ (Windows, free).
Vim and Emacs are also cool if you know how to use them.
The personal preference of the author is to have both an IDE for projects and a lightweight editor for quick and
easy file editing.
I’m using:
As an IDE for JS – WebStorm (I switch to one of the other JetBrains offerings when using other languages)
As a lightweight editor – Sublime Text or Atom.
The editors in the lists above are those that either I or my friends whom I consider good developers have been
using for a long time and are happy with.
There are other great editors in our big world. Please choose the one you like the most.
The choice of an editor, like any other tool, is individual and depends on your projects, habits, and personal
preferences.
IDE
Lightweight editors
My favorites
Let’s not argue
Comments
!
Chapter
An introduction
Lesson navigation
IDE
Lightweight editors
My favorites
Let’s not argue
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language An introduction
Developer console
Code is prone to errors. You will quite likely make errors… Oh, what am I talking about? You are absolutely going
to make errors, at least if you’re a human, not a robot.
But in the browser, users don’t see errors by default. So, if something goes wrong in the script, we won’t see
what’s broken and can’t fix it.
To see errors and get a lot of other useful information about scripts, “developer tools” have been embedded in
browsers.
Most developers lean towards Chrome or Firefox for development because those browsers have the best
developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually
playing “catch-up” to Chrome or Firefox. So most developers have a “favorite” browser and switch to others if a
problem is browser-specific.
Developer tools are potent; they have many features. To start, we’ll learn how to open them, look at errors, and
run JavaScript commands.
Open the page bug.html.
There’s an error in the JavaScript code on it. It’s hidden from a regular visitor’s eyes, so let’s open developer tools
to see it.
Press F12 or, if you’re on Mac, then Cmd+Opt+J .
The developer tools will open on the Console tab by default.
It looks somewhat like this:
The exact look of developer tools depends on your version of Chrome. It changes from time to time but should
be similar.
Here we can see the red-colored error message. In this case, the script contains an unknown “lalala”
command.
On the right, there is a clickable link to the source bug.html:12 with the line number where the error has
occurred.
Below the error message, there is a blue > symbol. It marks a “command line” where we can type JavaScript
commands. Press Enter to run them ( Shift+Enter to input multi-line commands).
Now we can see errors, and that’s enough for a start. We’ll come back to developer tools later and cover
debugging more in-depth in the chapter Debugging in Chrome.
Most other browsers use F12 to open developer tools.
The look & feel of them is quite similar. Once you know how to use one of these tools (you can start with
Chrome), you can easily switch to another.
Safari (Mac browser, not supported by Windows/Linux) is a little bit special here. We need to enable the “Develop
menu” first.
Open Preferences and go to the “Advanced” pane. There’s a checkbox at the bottom:
Now Cmd+Opt+C can toggle the console. Also, note that the new top menu item named “Develop” has
appeared. It has many commands and options.
Developer tools allow us to see errors, run commands, examine variables, and much more.
They can be opened with F12 for most browsers on Windows. Chrome for Mac needs Cmd+Opt+J , Safari:
Cmd+Opt+C (need to enable first).
Now we have the environment ready. In the next section, we’ll get down to JavaScript.
Google Chrome
Firefox, Edge, and others
Safari
Summary
Comments
!
Chapter
An introduction
Lesson navigation
Google Chrome
Firefox, Edge, and others
Safari
Summary
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Hello, world!
The tutorial that you’re reading is about core JavaScript, which is platform-independent. Later on, you’ll learn
about Node.JS and other platforms that use it.
But we need a working environment to run our scripts and, since this book is online, the browser is a good
choice. We’ll keep the amount of browser-specific commands (like alert ) to a minimum so that you don’t
spend time on them if you plan to concentrate on another environment (like Node.JS). We’ll focus on JavaScript
in the browser in the next part of the tutorial.
So first, let’s see how we attach a script to a webpage. For server-side environments (like Node.JS), you can
execute the script with a command like "node my.js" .
JavaScript programs can be inserted into any part of an HTML document with the help of the <script> tag.
For instance:
You can run the example by clicking the “Play” button in the right-top corner of the box above.
The <script> tag contains JavaScript code which is automatically executed when the browser processes the
tag.
The <script> tag has a few attributes that are rarely used nowadays but can still be found in old code:
The type attribute: <script type=…>
The old HTML standard, HTML4, required a script to have a type . Usually it was type="text/javascript" . It’s
not required anymore. Also, the modern HTML standard, HTML5, totally changed the meaning of this attribute.
Now, it can be used for JavaScript modules. But that’s an advanced topic; we’ll talk about modules in another part
of the tutorial.
The language attribute: <script language=…>
This attribute was meant to show the language of the script. This attribute no longer makes sense because
JavaScript is the default language. There is no need to use it.
Comments before and after scripts.
In really ancient books and guides, you may find comments inside <script> tags, like this:
This trick isn’t used in modern JavaScript. These comments hid JavaScript code from old browsers that didn’t
know how to process the <script> tag. Since browsers released in the last 15 years don’t have this issue, this
kind of comment can help you identify really old code.
If we have a lot of JavaScript code, we can put it into a separate file.
Script files are attached to HTML with the src attribute:
Here, /path/to/script.js is an absolute path to the script file (from the site root).
You can also provide a relative path from the current page. For instance, src="script.js" would mean a file
"script.js" in the current folder.
We can give a full URL as well. For instance:
To attach several scripts, use multiple tags:
Please note:
As a rule, only the simplest scripts are put into HTML. More complex ones reside in separate files.
The benefit of a separate file is that the browser will download it and store it in its cache.
Other pages that reference the same script will take it from the cache instead of downloading it, so the
file is actually downloaded only once.
That reduces traffic and makes pages faster.
If src is set, the script content is ignored.
A single <script> tag can’t have both the src attribute and code inside.
This won’t work:
We must choose either an external <script src="…"> or a regular <script> with code.
The example above can be split into two scripts to work:
We can use a <script> tag to add JavaScript code to a page.
The type and language attributes are not required.
A script in an external file can be inserted with <script src="path/to/script.js"></script> .
There is much more to learn about browser scripts and their interaction with the webpage. But let’s keep in mind
that this part of the tutorial is devoted to the JavaScript language, so we shouldn’t distract ourselves with
browser-specific implementations of it. We’ll be using the browser as a way to run JavaScript, which is very
convenient for online reading, but only one of many.
importance: 5
Create a page that shows a message “I’m JavaScript!”.
Do it in a sandbox, or on your hard drive, doesn’t matter, just ensure that it works.
Demo in new window
solution
importance: 5
Take the solution of the previous task Show an alert. Modify it by extracting the script content into an external
file alert.js , residing in the same folder.
Open the page, ensure that the alert works.
solution
The “script” tag
<!DOCTYPE HTML>
<html>
<body>
<p>Before the script...</p>
<script>
</script>
<p>...After the script.</p>
</body>
</html>
alert( 'Hello, world!' );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Modern markup
<script type="text/javascript"><!--
...
//--></script>
1
2
3
External scripts
<script src="/path/to/script.js"></script>1
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js"></script>1
<script src="/js/script1.js"></script>
<script src="/js/script2.js"></script>
1
2
3
<script src="file.js">
</script>
alert(1); // the content is ignored, because src is set
1
2
3
<script src="file.js"></script>
<script>
</script>
alert(1);
1
2
3
4
Summary
Tasks
Show an alert
Show an alert with an external script
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
The “script” tag
Modern markup
External scripts
Summary
Tasks (2)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Code structure
The first thing we’ll study is the building blocks of code.
Statements are syntax constructs and commands that perform actions.
We’ve already seen a statement, alert('Hello, world!') , which shows the message “Hello world!”.
We can have as many statements in our code as we want. Statements can be separated with a semicolon.
For example, here we split “Hello World” into two alerts:
Usually, statements are written on separate lines to make the code more readable:
A semicolon may be omitted in most cases when a line break exists.
This would also work:
Here, JavaScript interprets the line break as an “implicit” semicolon. This is called an automatic semicolon
insertion.
In most cases, a newline implies a semicolon. But “in most cases” does not mean “always”!
There are cases when a newline does not mean a semicolon. For example:
The code outputs 6 because JavaScript does not insert semicolons here. It is intuitively obvious that if the line
ends with a plus "+" , then it is an “incomplete expression”, so the semicolon is not required. And in this case
that works as intended.
But there are situations where JavaScript “fails” to assume a semicolon where it is really needed.
Errors which occur in such cases are quite hard to find and fix.
An example of an error
If you’re curious to see a concrete example of such an error, check this code out:
No need to think about the meaning of the brackets [] and forEach yet. We’ll study them later. For
now, just remember the result of the code: it shows 1 then 2 .
Now, let’s add an alert before the code and not finish it with a semicolon:
Now if we run the code, only the first alert is shown and then we have an error!
But everything is fine again if we add a semicolon after alert :
Now we have the “All fine now” message followed by 1 and 2 .
The error in the no-semicolon variant occurs because JavaScript does not assume a semicolon before
square brackets [...] .
So, because the semicolon is not auto-inserted, the code in the first example is treated as a single
statement. Here’s how the engine sees it:
But it should be two separate statements, not one. Such a merging in this case is just wrong, hence the
error. This can happen in other situations.
We recommend putting semicolons between statements even if they are separated by newlines. This rule is
widely adopted by the community. Let’s note once again – it is possible to leave out semicolons most of the time.
But it’s safer – especially for a beginner – to use them.
As time goes on, programs become more and more complex. It becomes necessary to add comments which
describe what the code does and why.
Comments can be put into any place of a script. They don’t affect its execution because the engine simply
ignores them.
One-line comments start with two forward slash characters // .
The rest of the line is a comment. It may occupy a full line of its own or follow a statement.
Like here:
Multiline comments start with a forward slash and an asterisk /* and end with an asterisk and a forward
slash */ .
Like this:
The content of comments is ignored, so if we put code inside /* … */ , it won’t execute.
Sometimes it can be handy to temporarily disable a part of code:
Use hotkeys!
In most editors, a line of code can be commented out by pressing the Ctrl+/ hotkey for a single-line
comment and something like Ctrl+Shift+/ – for multiline comments (select a piece of code and press
the hotkey). For Mac, try Cmd instead of Ctrl .
Nested comments are not supported!
There may not be /*...*/ inside another /*...*/ .
Such code will die with an error:
Please, don’t hesitate to comment your code.
Comments increase the overall code footprint, but that’s not a problem at all. There are many tools which minify
code before publishing to a production server. They remove comments, so they don’t appear in the working
scripts. Therefore, comments do not have negative effects on production at all.
Later in the tutorial there will be a chapter Coding Style that also explains how to write better comments.
Statements
alert('Hello'); alert('World');1
alert('Hello');
alert('World');
1
2
Semicolons
alert('Hello')
alert('World')
1
2
alert(3 +
1
+ 2);
1
2
3
[1, 2].forEach(alert)1
alert("There will be an error")
[1, 2].forEach(alert)
1
2
3
alert("All fine now");
[1, 2].forEach(alert)
1
2
3
alert("There will be an error")[1, 2].forEach(alert)1
Comments
// This comment occupies a line of its own
alert('Hello');
alert('World'); // This comment follows the statement
1
2
3
4
/* An example with two messages.
This is a multiline comment.
*/
alert('Hello');
alert('World');
1
2
3
4
5
/* Commenting out the code
alert('Hello');
*/
alert('World');
1
2
3
4
/*
/* nested comment ?!? */
*/
alert( 'World' );
1
2
3
4
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
Statements
Semicolons
Comments
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
The modern mode, "use strict"
For a long time, JavaScript evolved without compatibility issues. New features were added to the language while
old functionality didn’t change.
That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect
decision made by JavaScript’s creators got stuck in the language forever.
This was the case until 2009 when ECMAScript 5 (ES5) appeared. It added new features to the language and
modified some of the existing ones. To keep the old code working, most modifications are off by default. You
need to explicitly enable them with a special directive: "use strict" .
The directive looks like a string: "use strict" or 'use strict' . When it is located at the top of a script, the
whole script works the “modern” way.
For example:
We will learn functions (a way to group commands) soon.
Looking ahead, let’s just note that "use strict" can be put at the start of most kinds of functions instead of
the whole script. Doing that enables strict mode in that function only. But usually, people use it for the whole
script.
Ensure that “use strict” is at the top
Please make sure that "use strict" is at the top of your scripts, otherwise strict mode may not be
enabled.
Strict mode isn’t enabled here:
Only comments may appear above "use strict" .
There’s no way to cancel use strict
There is no directive like "no use strict" that reverts the engine to old behavior.
Once we enter strict mode, there’s no return.
We have yet to cover the differences between strict mode and the “default” mode.
In the next chapters, as we learn language features, we’ll note the differences between the strict and default
modes. Luckily, there aren’t many and they actually make our lives better.
For now, it’s enough to know about it in general:
1. The "use strict" directive switches the engine to the “modern” mode, changing the behavior of some
built-in features. We’ll see the details later in the tutorial.
2. Strict mode is enabled by placing "use strict" at the top of a script or function. Several language features,
like “classes” and “modules”, enable strict mode automatically.
3. Strict mode is supported by all modern browsers.
4. We recommended always starting scripts with "use strict" . All examples in this tutorial assume strict
mode unless (very rarely) specified otherwise.
“use strict”
"use strict";
// this code works the modern way
...
1
2
3
4
alert("some code");
// "use strict" below is ignored--it must be at the top
"use strict";
// strict mode is not activated
1
2
3
4
5
6
Always “use strict”
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
“use strict”
Always “use strict”
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Variables
Most of the time, a JavaScript application needs to work with information. Here are two examples:
1. An online shop – the information might include goods being sold and a shopping cart.
2. A chat application – the information might include users, messages, and much more.
Variables are used to store this information.
A variable is a “named storage” for data. We can use variables to store goodies, visitors, and other data.
To create a variable in JavaScript, use the let keyword.
The statement below creates (in other words: declares or defines) a variable with the name “message”:
Now, we can put some data into it by using the assignment operator = :
The string is now saved into the memory area associated with the variable. We can access it using the variable
name:
To be concise, we can combine the variable declaration and assignment into a single line:
We can also declare multiple variables in one line:
That might seem shorter, but we don’t recommended it. For the sake of better readability, please use a single line
per variable.
The multiline variant is a bit longer, but easier to read:
Some people also define multiple variables in this multiline style:
…Or even in the “comma-first” style:
Technically, all these variants do the same thing. So, it’s a matter of personal taste and aesthetics.
var instead of let
In older scripts, you may also find another keyword: var instead of let :
The var keyword is almost the same as let . It also declares a variable, but in a slightly different, “old-
school” way.
There are subtle differences between let and var , but they do not matter for us yet. We’ll cover them
in detail in the chapter The old "var".
We can easily grasp the concept of a “variable” if we imagine it as a “box” for data, with a uniquely-named sticker
on it.
For instance, the variable message can be imagined as a box labeled "message" with the value "Hello!" in
it:
We can put any value in the box.
We can also change it as many times as we want:
When the value is changed, the old data is removed from the variable:
We can also declare two variables and copy data from one into the other.
Functional languages
It’s interesting to note that functional programming languages, like Scala or Erlang, forbid changing
variable values.
In such languages, once the value is stored “in the box”, it’s there forever. If we need to store something
else, the language forces us to create a new box (declare a new variable). We can’t reuse the old one.
Though it may seem a little odd at first sight, these languages are quite capable of serious development.
More than that, there are areas like parallel computations where this limitation confers certain benefits.
Studying such a language (even if you’re not planning to use it soon) is recommended to broaden the
mind.
There are two limitations on variable names in JavaScript:
1. The name must contain only letters, digits, or the symbols $ and _ .
2. The first character must not be a digit.
Examples of valid names:
When the name contains multiple words, camelCase is commonly used. That is: words go one after another, each
word starting with a capital letter: myVeryLongName .
What’s interesting – the dollar sign '$' and the underscore '_' can also be used in names. They are regular
symbols, just like letters, without any special meaning.
These names are valid:
Examples of incorrect variable names:
Case matters
Variables named apple and AppLE are two different variables.
Non-English letters are allowed, but not recommended
It is possible to use any language, including cyrillic letters or even hieroglyphs, like this:
Technically, there is no error here, such names are allowed, but there is an international tradition to use
English in variable names. Even if we’re writing a small script, it may have a long life ahead. People from
other countries may need to read it some time.
Reserved names
There is a list of reserved words, which cannot be used as variable names because they are used by the
language itself.
For example: let , class , return , and function are reserved.
The code below gives a syntax error:
An assignment without use strict
Normally, we need to define a variable before using it. But in the old times, it was technically possible to
create a variable by a mere assignment of the value without using let . This still works now if we don’t
put use strict in our scripts to maintain compatibility with old scripts.
This is a bad practice and would cause an error in strict mode:
To declare a constant (unchanging) variable, use const instead of let :
Variables declared using const are called “constants”. They cannot be changed. An attempt to do so would
cause an error:
When a programmer is sure that a variable will never change, they can declare it with const to guarantee and
clearly communicate that fact to everyone.
There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior
to execution.
Such constants are named using capital letters and underscores.
Like this:
Benefits:
COLOR_ORANGE is much easier to remember than "#FF7F00" .
It is much easier to mistype "#FF7F00" than COLOR_ORANGE .
When reading the code, COLOR_ORANGE is much more meaningful than #FF7F00 .
When should we use capitals for a constant and when should we name it normally? Let’s make that clear.
Being a “constant” just means that a variable’s value never changes. But there are constants that are known prior
to execution (like a hexadecimal value for red) and there are constants that are calculated in run-time, during the
execution, but do not change after their initial assignment.
For instance:
The value of pageLoadTime is not known prior to the page load, so it’s named normally. But it’s still a constant
because it doesn’t change after assignment.
In other words, capital-named constants are only used as aliases for “hard-coded” values.
Talking about variables, there’s one more extremely important thing.
Please name your variables sensibly. Take time to think about this.
Variable naming is one of the most important and complex skills in programming. A quick glance at variable
names can reveal which code was written by a beginner versus an experienced developer.
In a real project, most of the time is spent modifying and extending an existing code base rather than writing
something completely separate from scratch. When we return to some code after doing something else for a
while, it’s much easier to find information that is well-labeled. Or, in other words, when the variables have good
names.
Please spend time thinking about the right name for a variable before declaring it. Doing so will repay you
handsomely.
Some good-to-follow rules are:
Use human-readable names like userName or shoppingCart .
Stay away from abbreviations or short names like a , b , c , unless you really know what you’re doing.
Make names maximally descriptive and concise. Examples of bad names are data and value . Such names
say nothing. It’s only okay to use them if the context of the code makes it exceptionally obvious which data or
value the variable is referencing.
Agree on terms within your team and in your own mind. If a site visitor is called a “user” then we should name
related variables currentUser or newUser instead of currentVisitor or newManInTown .
Sounds simple? Indeed it is, but creating descriptive and concise variable names in practice is not. Go for it.
Reuse or create?
And the last note. There are some lazy programmers who, instead of declaring new variables, tend to
reuse existing ones.
As a result, their variables are like boxes into which people throw different things without changing their
stickers. What’s inside the box now? Who knows? We need to come closer and check.
Such programmers save a little bit on variable declaration but lose ten times more on debugging.
An extra variable is good, not evil.
Modern JavaScript minifiers and browsers optimize code well enough, so it won’t create performance
issues. Using different variables for different values can even help the engine optimize your code.
We can declare variables to store data by using the var , let , or const keywords.
let – is a modern variable declaration. The code must be in strict mode to use let in Chrome (V8).
var – is an old-school variable declaration. Normally we don’t use it at all, but we’ll cover subtle differences
from let in the chapter The old "var", just in case you need them.
const – is like let , but the value of the variable can’t be changed.
Variables should be named in a way that allows us to easily understand what’s inside them.
importance: 2
1. Declare two variables: admin and name .
2. Assign the value "John" to name .
3. Copy the value from name to admin .
4. Show the value of admin using alert (must output “John”).
solution
importance: 3
1. Create a variable with the name of our planet. How would you name such a variable?
2. Create a variable to store the name of a current visitor to a website. How would you name that variable?
solution
importance: 4
Examine the following code:
Here we have a constant birthday date and the age is calculated from birthday with the help of some code
(it is not provided for shortness, and because details don’t matter here).
Would it be right to use upper case for birthday ? For age ? Or even for both?
solution
A variable
let message;1
let message;
message = 'Hello'; // store the string
1
2
3
let message;
message = 'Hello!';
alert(message); // shows the variable content
1
2
3
4
let message = 'Hello!'; // define the variable and assign the value
alert(message); // Hello!
1
2
3
let user = 'John', age = 25, message = 'Hello';1
let user = 'John';
let age = 25;
let message = 'Hello';
1
2
3
let user = 'John',
age = 25,
message = 'Hello';
1
2
3
let user = 'John'
, age = 25
, message = 'Hello';
1
2
3
var message = 'Hello';1
A real-life analogy
let message;
message = 'Hello!';
message = 'World!'; // value changed
alert(message);
1
2
3
4
5
6
7
let hello = 'Hello world!';
let message;
// copy 'Hello world' from hello into message
message = hello;
// now two variables hold the same data
alert(hello); // Hello world!
alert(message); // Hello world!
1
2
3
4
5
6
7
8
9
10
Variable naming
let userName;
let test123;
1
2
let $ = 1; // declared a variable with the name "$"
let _ = 2; // and now a variable with the name "_"
alert($ + _); // 3
1
2
3
4
let 1a; // cannot start with a digit
let my-name; // hyphens '-' aren't allowed in the name
1
2
3
let имя = '...';
let = '...';
1
2
let let = 5; // can't name a variable "let", error!
let return = 5; // also can't name it "return", error!
1
2
// note: no "use strict" in this example
num = 5; // the variable "num" is created if it didn't exist
alert(num); // 5
1
2
3
4
5
"use strict";
num = 5; // error: num is not defined
1
2
3
Constants
const myBirthday = '18.04.1982';1
const myBirthday = '18.04.1982';
myBirthday = '01.01.2001'; // error, can't reassign the constant!
1
2
3
Uppercase constants
const COLOR_RED = "#F00";
const COLOR_GREEN = "#0F0";
const COLOR_BLUE = "#00F";
const COLOR_ORANGE = "#FF7F00";
// ...when we need to pick a color
let color = COLOR_ORANGE;
alert(color); // #FF7F00
1
2
3
4
5
6
7
8
const pageLoadTime = /* time taken by a webpage to load */;1
Name things right
Summary
Tasks
Working with variables
Giving the right name
Uppercase const?
const birthday = '18.04.1982';
const age = someCode(birthday);
1
2
3
const BIRTHDAY = '18.04.1982'; // make uppercase?
const AGE = someCode(BIRTHDAY); // make uppercase?
1
2
3
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
A variable
A real-life analogy
Variable naming
Constants
Name things right
Summary
Tasks (3)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Data types
A variable in JavaScript can contain any data. A variable can at one moment be a string and at another be a
number:
Programming languages that allow such things are called “dynamically typed”, meaning that there are data types,
but variables are not bound to any of them.
There are seven basic data types in JavaScript. Here, we’ll cover them in general and in the next chapters we’ll talk
about each of them in detail.
The number type represents both integer and floating point numbers.
There are many operations for numbers, e.g. multiplication * , division / , addition + , subtraction - , and so on.
Besides regular numbers, there are so-called “special numeric values” which also belong to this data type:
Infinity , -Infinity and NaN .
Infinity represents the mathematical Infinity ∞. It is a special value that’s greater than any number.
We can get it as a result of division by zero:
Or just reference it directly:
NaN represents a computational error. It is a result of an incorrect or an undefined mathematical operation,
for instance:
NaN is sticky. Any further operation on NaN returns NaN :
So, if there’s a NaN somewhere in a mathematical expression, it propagates to the whole result.
Mathematical operations are safe
Doing maths is “safe” in JavaScript. We can do anything: divide by zero, treat non-numeric strings as
numbers, etc.
The script will never stop with a fatal error (“die”). At worst, we’ll get NaN as the result.
Special numeric values formally belong to the “number” type. Of course they are not numbers in the common
sense of this word.
We’ll see more about working with numbers in the chapter Numbers.
A string in JavaScript must be surrounded by quotes.
In JavaScript, there are 3 types of quotes.
1. Double quotes: "Hello" .
2. Single quotes: 'Hello' .
3. Backticks: `Hello` .
Double and single quotes are “simple” quotes. There’s no difference between them in JavaScript.
Backticks are “extended functionality” quotes. They allow us to embed variables and expressions into a string by
wrapping them in ${…} , for example:
The expression inside ${…} is evaluated and the result becomes a part of the string. We can put anything in
there: a variable like name or an arithmetical expression like 1 + 2 or something more complex.
Please note that this can only be done in backticks. Other quotes don’t have this embedding functionality!
We’ll cover strings more thoroughly in the chapter Strings.
There is no character type.
In some languages, there is a special “character” type for a single character. For example, in the C
language and in Java it is char .
In JavaScript, there is no such type. There’s only one type: string . A string may consist of only one
character or many of them.
The boolean type has only two values: true and false .
This type is commonly used to store yes/no values: true means “yes, correct”, and false means “no,
incorrect”.
For instance:
Boolean values also come as a result of comparisons:
We’ll cover booleans more deeply in the chapter Logical operators.
The special null value does not belong to any of the types described above.
It forms a separate type of its own which contains only the null value:
In JavaScript, null is not a “reference to a non-existing object” or a “null pointer” like in some other languages.
It’s just a special value which represents “nothing”, “empty” or “value unknown”.
The code above states that age is unknown or empty for some reason.
The special value undefined also stands apart. It makes a type of its own, just like null .
The meaning of undefined is “value is not assigned”.
If a variable is declared, but not assigned, then its value is undefined :
Technically, it is possible to assign undefined to any variable:
…But we don’t recommend doing that. Normally, we use null to assign an “empty” or “unknown” value to a
variable, and we use undefined for checks like seeing if a variable has been assigned.
The object type is special.
All other types are called “primitive” because their values can contain only a single thing (be it a string or a
number or whatever). In contrast, objects are used to store collections of data and more complex entities. We’ll
deal with them later in the chapter Objects after we learn more about primitives.
The symbol type is used to create unique identifiers for objects. We have to mention it here for completeness,
but it’s better to study this type after objects.
The typeof operator returns the type of the argument. It’s useful when we want to process values of different
types differently or just want to do a quick check.
It supports two forms of syntax:
1. As an operator: typeof x .
2. As a function: typeof(x) .
In other words, it works with parentheses or without them. The result is the same.
The call to typeof x returns a string with the type name:
The last three lines may need additional explanation:
1. Math is a built-in object that provides mathematical operations. We will learn it in the chapter Numbers.
Here, it serves just as an example of an object.
2. The result of typeof null is "object" . That’s wrong. It is an officially recognized error in typeof , kept for
compatibility. Of course, null is not an object. It is a special value with a separate type of its own. So, again,
this is an error in the language.
3. The result of typeof alert is "function" , because alert is a function of the language. We’ll study
functions in the next chapters where we’ll see that there’s no special “function” type in JavaScript. Functions
belong to the object type. But typeof treats them differently. Formally, it’s incorrect, but very convenient in
practice.
There are 7 basic types in JavaScript.
number for numbers of any kind: integer or floating-point.
string for strings. A string may have one or more characters, there’s no separate single-character type.
boolean for true / false .
null for unknown values – a standalone type that has a single value null .
undefined for unassigned values – a standalone type that has a single value undefined .
object for more complex data structures.
symbol for unique identifiers.
The typeof operator allows us to see which type is stored in a variable.
Two forms: typeof x or typeof(x) .
Returns a string with the name of the type, like "string" .
For null returns "object" – this is an error in the language, it’s not actually an object.
In the next chapters, we’ll concentrate on primitive values and once we’re familiar with them, we’ll move on to
objects.
importance: 5
What is the output of the script?
solution
// no error
let message = "hello";
message = 123456;
1
2
3
A number
let n = 123;
n = 12.345;
1
2
alert( 1 / 0 ); // Infinity1
alert( Infinity ); // Infinity1
alert( "not a number" / 2 ); // NaN, such division is erroneous1
alert( "not a number" / 2 + 5 ); // NaN1
A string
let str = "Hello";
let str2 = 'Single quotes are ok too';
let phrase = `can embed ${str}`;
1
2
3
let name = "John";
// embed a variable
alert( `Hello, ${name}!` ); // Hello, John!
// embed an expression
alert( `the result is ${1 + 2}` ); // the result is 3
1
2
3
4
5
6
7
alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do nothing)1
A boolean (logical type)
let nameFieldChecked = true; // yes, name field is checked
let ageFieldChecked = false; // no, age field is not checked
1
2
let isGreater = 4 > 1;
alert( isGreater ); // true (the comparison result is "yes")
1
2
3
The “null” value
let age = null;1
The “undefined” value
let x;
alert(x); // shows "undefined"
1
2
3
let x = 123;
x = undefined;
alert(x); // "undefined"
1
2
3
4
5
Objects and Symbols
The typeof operator
typeof undefined // "undefined"
typeof 0 // "number"
typeof true // "boolean"
typeof "foo" // "string"
typeof Symbol("id") // "symbol"
typeof Math // "object" (1)
typeof null // "object" (2)
typeof alert // "function" (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Summary
Tasks
String quotes
let name = "Ilya";
alert( `hello ${1}` ); // ?
alert( `hello ${"name"}` ); // ?
alert( `hello ${name}` ); // ?
1
2
3
4
5
6
7
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
A number
A string
A boolean (logical type)
The “null” value
The “undefined” value
Objects and Symbols
The typeof operator
Summary
Tasks (1)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Type Conversions
Most of the time, operators and functions automatically convert the values given to them to the right type. This is
called “type conversion”.
For example, alert automatically converts any value to a string to show it. Mathematical operations convert
values to numbers.
There are also cases when we need to explicitly convert a value to the expected type.
Not talking about objects yet
In this chapter, we won’t cover objects. Instead, we’ll study primitives first. Later, after we learn about
objects, we’ll see how object conversion works in the chapter Object to primitive conversion.
String conversion happens when we need the string form of a value.
For example, alert(value) does it to show the value.
We can also call the String(value) function to convert a value to a string:
String conversion is mostly obvious. A false becomes "false" , null becomes "null" , etc.
Numeric conversion happens in mathematical functions and expressions automatically.
For example, when division / is applied to non-numbers:
We can use the Number(value) function to explicitly convert a value to a number:
Explicit conversion is usually required when we read a value from a string-based source like a text form but
expect a number to be entered.
If the string is not a valid number, the result of such a conversion is NaN . For instance:
Numeric conversion rules:
Value Becomes…
undefined NaN
null 0
true and false 1 and 0
string
Whitespaces from the start and end are removed. If the remaining string is empty, the result is
0 . Otherwise, the number is “read” from the string. An error gives NaN .
Examples:
Please note that null and undefined behave differently here: null becomes zero while undefined
becomes NaN .
Addition ‘+’ concatenates strings
Almost all mathematical operations convert values to numbers. A notable exception is addition + . If one
of the added values is a string, the other one is also converted to a string.
Then, it concatenates (joins) them:
This only happens when at least one of the arguments is a string. Otherwise, values are converted to
numbers.
Boolean conversion is the simplest one.
It happens in logical operations (later we’ll meet condition tests and other similar things) but can also be
performed explicitly with a call to Boolean(value) .
The conversion rule:
Values that are intuitively “empty”, like 0 , an empty string, null , undefined , and NaN , become false .
Other values become true .
For instance:
Please note: the string with zero "0" is true
Some languages (namely PHP) treat "0" as false . But in JavaScript, a non-empty string is always
true .
The three most widely used type conversions are to string, to number, and to boolean.
ToString – Occurs when we output something. Can be performed with String(value) . The conversion to
string is usually obvious for primitive values.
ToNumber – Occurs in math operations. Can be performed with Number(value) .
The conversion follows the rules:
Value Becomes…
undefined NaN
null 0
true / false 1 / 0
string
The string is read “as is”, whitespaces from both sides are ignored. An empty string becomes 0 .
An error gives NaN .
ToBoolean – Occurs in logical operations. Can be performed with Boolean(value) .
Follows the rules:
Value Becomes…
0 , null , undefined , NaN , "" false
any other value true
Most of these rules are easy to understand and memorize. The notable exceptions where people usually make
mistakes are:
undefined is NaN as a number, not 0 .
"0" and space-only strings like " " are true as a boolean.
Objects aren’t covered here. We’ll return to them later in the chapter Object to primitive conversion that is
devoted exclusively to objects after we learn more basic things about JavaScript.
importance: 5
What are results of these expressions?
Think well, write down and then compare with the answer.
solution
ToString
let value = true;
alert(typeof value); // boolean
value = String(value); // now value is a string "true"
alert(typeof value); // string
1
2
3
4
5
ToNumber
alert( "6" / "2" ); // 3, strings are converted to numbers1
let str = "123";
alert(typeof str); // string
let num = Number(str); // becomes a number 123
alert(typeof num); // number
1
2
3
4
5
6
let age = Number("an arbitrary string instead of a number");
alert(age); // NaN, conversion failed
1
2
3
alert( Number(" 123 ") ); // 123
alert( Number("123z") ); // NaN (error reading a number at "z")
alert( Number(true) ); // 1
alert( Number(false) ); // 0
1
2
3
4
alert( 1 + '2' ); // '12' (string to the right)
alert( '1' + 2 ); // '12' (string to the left)
1
2
ToBoolean
alert( Boolean(1) ); // true
alert( Boolean(0) ); // false
alert( Boolean("hello") ); // true
alert( Boolean("") ); // false
1
2
3
4
5
alert( Boolean("0") ); // true
alert( Boolean(" ") ); // spaces, also true (any non-empty string is true)
1
2
Summary
Tasks
Type conversions
"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
7 / 0
" -9 " + 5
" -9 " - 5
null + 1
undefined + 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
ToString
ToNumber
ToBoolean
Summary
Tasks (1)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Operators
We know many operators from school. They are things like addition + , multiplication * , subtraction - , and so
on.
In this chapter, we’ll concentrate on aspects of operators that are not covered by school arithmetic.
Before we move on, let’s grasp some common terminology.
An operand – is what operators are applied to. For instance, in the multiplication of 5 * 2 there are two
operands: the left operand is 5 and the right operand is 2 . Sometimes, people call these “arguments”
instead of “operands”.
An operator is unary if it has a single operand. For example, the unary negation - reverses the sign of a
number:
An operator is binary if it has two operands. The same minus exists in binary form as well:
Formally, we’re talking about two different operators here: the unary negation (single operand: reverses the
sign) and the binary subtraction (two operands: subtracts).
Now, let’s see special features of JavaScript operators that are beyond school arithmetics.
Usually, the plus operator + sums numbers.
But, if the binary + is applied to strings, it merges (concatenates) them:
Note that if one of the operands is a string, the other one is converted to a string too.
For example:
See, it doesn’t matter whether the first operand is a string or the second one. The rule is simple: if either operand
is a string, the other one is converted into a string as well.
However, note that operations run from left to right. If there are two numbers followed by a string, the numbers
will be added before being converted to a string:
String concatenation and conversion is a special feature of the binary plus + . Other arithmetic operators work
only with numbers and always convert their operands to numbers.
For instance, subtraction and division:
The plus + exists in two forms: the binary form that we used above and the unary form.
The unary plus or, in other words, the plus operator + applied to a single value, doesn’t do anything to numbers.
But if the operand is not a number, the unary plus converts it into a number.
For example:
It actually does the same thing as Number(...) , but is shorter.
The need to convert strings to numbers arises very often. For example, if we are getting values from HTML form
fields, they are usually strings.
What if we want to sum them?
The binary plus would add them as strings:
If we want to treat them as numbers, we need to convert and then sum them:
From a mathematician’s standpoint, the abundance of pluses may seem strange. But from a programmer’s
standpoint, there’s nothing special: unary pluses are applied first, they convert strings to numbers, and then the
binary plus sums them up.
Why are unary pluses applied to values before the binary ones? As we’re going to see, that’s because of their
higher precedence.
If an expression has more than one operator, the execution order is defined by their precedence, or, in other
words, the implicit priority order of operators.
From school, we all know that the multiplication in the expression 1 + 2 * 2 should be calculated before the
addition. That’s exactly the precedence thing. The multiplication is said to have a higher precedence than the
addition.
Parentheses override any precedence, so if we’re not satisfied with the implicit order, we can use them to change
it. For example: (1 + 2) * 2 .
There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with
the larger number executes first. If the precedence is the same, the execution order is from left to right.
Here’s an extract from the precedence table (you don’t need to remember this, but note that unary operators are
higher than corresponding binary ones):
Precedence Name Sign
16 unary plus +
16 unary negation -
14 multiplication *
14 division /
13 addition +
13 subtraction -
3 assignment =
As we can see, the “unary plus” has a priority of 16 which is higher than the 13 of “addition” (binary plus).
That’s why, in the expression "+apples + +oranges" , unary pluses work before the addition.
Let’s note that an assignment = is also an operator. It is listed in the precedence table with the very low priority
of 3 .
That’s why, when we assign a variable, like x = 2 * 2 + 1 , the calculations are done first and then the = is
evaluated, storing the result in x .
It is possible to chain assignments:
Chained assignments evaluate from right to left. First, the rightmost expression 2 + 2 is evaluated and then
assigned to the variables on the left: c , b and a . At the end, all the variables share a single value.
The assignment operator "=" returns a value
An operator always returns a value. That’s obvious for most of them like addition + or multiplication * .
But the assignment operator follows this rule too.
The call x = value writes the value into x and then returns it.
Here’s a demo that uses an assignment as part of a more complex expression:
In the example above, the result of (a = b + 1) is the value which is assigned to a (that is 3 ). It is
then used to subtract from 3 .
Funny code, isn’t it? We should understand how it works, because sometimes we see it in 3rd-party
libraries, but shouldn’t write anything like that ourselves. Such tricks definitely don’t make code clearer or
readable.
The remainder operator % , despite its appearance, is not related to percents.
The result of a % b is the remainder of the integer division of a by b .
For instance:
The exponentiation operator ** is a recent addition to the language.
For a natural number b , the result of a ** b is a multiplied by itself b times.
For instance:
The operator works for non-integer numbers of a and b as well.
For instance:
Increasing or decreasing a number by one is among the most common numerical operations.
So, there are special operators for it:
Increment ++ increases a variable by 1:
Decrement -- decreases a variable by 1:
Important:
Increment/decrement can only be applied to variables. Trying to use it on a value like 5++ will give an
error.
The operators ++ and -- can be placed either before or after a variable.
When the operator goes after the variable, it is in “postfix form”: counter++ .
The “prefix form” is when the operator goes before the variable: ++counter .
Both of these statements do the same thing: increase counter by 1 .
Is there any difference? Yes, but we can only see it if we use the returned value of ++/-- .
Let’s clarify. As we know, all operators return a value. Increment/decrement is no exception. The prefix form
returns the new value while the postfix form returns the old value (prior to increment/decrement).
To see the difference, here’s an example:
In the line (*) , the prefix form ++counter increments counter and returns the new value, 2 . So, the alert
shows 2 .
Now, let’s use the postfix form:
In the line (*) , the postfix form counter++ also increments counter but returns the old value (prior to
increment). So, the alert shows 1 .
To summarize:
If the result of increment/decrement is not used, there is no difference in which form to use:
If we’d like to increase a value and immediately use the result of the operator, we need the prefix form:
If we’d like to increment a value but use its previous value, we need the postfix form:
Increment/decrement among other operators
The operators ++/-- can be used inside expressions as well. Their precedence is higher than most other
arithmetical operations.
For instance:
Compare with:
Though technically okay, such notation usually makes code less readable. One line does multiple things –
not good.
While reading code, a fast “vertical” eye-scan can easily miss something like counter++ and it won’t be
obvious that the variable increased.
We advise a style of “one line – one action”:
Bitwise operators treat arguments as 32-bit integer numbers and work on the level of their binary representation.
These operators are not JavaScript-specific. They are supported in most programming languages.
The list of operators:
AND ( & )
OR ( | )
XOR ( ^ )
NOT ( ~ )
LEFT SHIFT ( << )
RIGHT SHIFT ( >> )
ZERO-FILL RIGHT SHIFT ( >>> )
These operators are used very rarely. To understand them, we need to delve into low-level number
representation and it would not be optimal to do that right now, especially since we won’t need them any time
soon. If you’re curious, you can read the Bitwise Operators article on MDN. It would be more practical to do that
when a real need arises.
We often need to apply an operator to a variable and store the new result in that same variable.
For example:
This notation can be shortened using the operators += and *= :
Short “modify-and-assign” operators exist for all arithmetical and bitwise operators: /= , -= , etc.
Such operators have the same precedence as a normal assignment, so they run after most other calculations:
The comma operator , is one of the rarest and most unusual operators. Sometimes, it’s used to write shorter
code, so we need to know it in order to understand what’s going on.
The comma operator allows us to evaluate several expressions, dividing them with a comma , . Each of them is
evaluated but only the result of the last one is returned.
For example:
Here, the first expression 1 + 2 is evaluated and its result is thrown away. Then, 3 + 4 is evaluated and
returned as the result.
Comma has a very low precedence
Please note that the comma operator has very low precedence, lower than = , so parentheses are
important in the example above.
Without them: a = 1 + 2, 3 + 4 evaluates + first, summing the numbers into a = 3, 7 , then the
assignment operator = assigns a = 3 , and finally the number after the comma, 7 , is not processed so
it’s ignored.
Why do we need an operator that throws away everything except the last part?
Sometimes, people use it in more complex constructs to put several actions in one line.
For example:
Such tricks are used in many JavaScript frameworks. That’s why we’re mentioning them. But, usually, they don’t
improve code readability so we should think well before using them.
importance: 5
What are the final values of all variables a , b , c and d after the code below?
solution
importance: 3
What are the values of a and x after the code below?
solution
Terms: “unary”, “binary”, “operand”
let x = 1;
x = -x;
alert( x ); // -1, unary negation was applied
1
2
3
4
let x = 1, y = 3;
alert( y - x ); // 2, binary minus subtracts values
1
2
String concatenation, binary +
let s = "my" + "string";
alert(s); // mystring
1
2
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
1
2
alert(2 + 2 + '1' ); // "41" and not "221"1
alert( 2 - '1' ); // 1
alert( '6' / '2' ); // 3
1
2
Numeric conversion, unary +
// No effect on numbers
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
// Converts non-numbers
alert( +true ); // 1
alert( +"" ); // 0
1
2
3
4
5
6
7
8
9
10
let apples = "2";
let oranges = "3";
alert( apples + oranges ); // "23", the binary plus concatenates strings
1
2
3
4
let apples = "2";
let oranges = "3";
// both values converted to numbers before the binary plus
alert( +apples + +oranges ); // 5
// the longer variant
// alert( Number(apples) + Number(oranges) ); // 5
1
2
3
4
5
6
7
8
Operator precedence
Assignment
let x = 2 * 2 + 1;
alert( x ); // 5
1
2
3
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
1
2
3
4
5
6
7
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
alert( a ); // 3
alert( c ); // 0
1
2
3
4
5
6
7
Remainder %
alert( 5 % 2 ); // 1 is a remainder of 5 divided by 2
alert( 8 % 3 ); // 2 is a remainder of 8 divided by 3
alert( 6 % 3 ); // 0 is a remainder of 6 divided by 3
1
2
3
Exponentiation **
alert( 2 ** 2 ); // 4 (2 * 2)
alert( 2 ** 3 ); // 8 (2 * 2 * 2)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2)
1
2
3
alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root, that's maths)
alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root)
1
2
Increment/decrement
let counter = 2;
counter++; // works the same as counter = counter + 1, but is shorter
alert( counter ); // 3
1
2
3
let counter = 2;
counter--; // works the same as counter = counter - 1, but is shorter
alert( counter ); // 1
1
2
3
let counter = 1;
let a = ++counter; // (*)
alert(a); // 2
1
2
3
4
let counter = 1;
let a = counter++; // (*) changed ++counter to counter++
alert(a); // 1
1
2
3
4
let counter = 0;
counter++;
++counter;
alert( counter ); // 2, the lines above did the same
1
2
3
4
let counter = 0;
alert( ++counter ); // 1
1
2
let counter = 0;
alert( counter++ ); // 0
1
2
let counter = 1;
alert( 2 * ++counter ); // 4
1
2
let counter = 1;
alert( 2 * counter++ ); // 2, because counter++ returns the "old" value
1
2
let counter = 1;
alert( 2 * counter );
counter++;
1
2
3
Bitwise operators
Modify-in-place
let n = 2;
n = n + 5;
n = n * 2;
1
2
3
let n = 2;
n += 5; // now n = 7 (same as n = n + 5)
n *= 2; // now n = 14 (same as n = n * 2)
alert( n ); // 14
1
2
3
4
5
let n = 2;
n *= 3 + 5;
alert( n ); // 16 (right part evaluated first, same as n *= 8)
1
2
3
4
5
Comma
let a = (1 + 2, 3 + 4);
alert( a ); // 7 (the result of 3 + 4)
1
2
3
// three operations in one line
for (a = 1, b = 3, c = a * b; a < 10; a++) {
...
}
1
2
3
4
Tasks
The postfix and prefix forms
let a = 1, b = 1;
let c = ++a; // ?
let d = b++; // ?
1
2
3
4
Assignment result
let a = 2;
let x = 1 + (a *= 2);
1
2
3
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
Terms: “unary”, “binary”,
“operand”
String concatenation, binary
+
Numeric conversion, unary +
Operator precedence
Assignment
Remainder %
Exponentiation **
Increment/decrement
Bitwise operators
Modify-in-place
Comma
Tasks (2)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Comparisons
We know many comparison operators from maths:
Greater/less than: a > b , a < b .
Greater/less than or equals: a >= b , a <= b .
Equals: a == b (please note the double equals sign = . A single symbol a = b would mean an assignment).
Not equals. In maths the notation is , but in JavaScript it’s written as an assignment with an exclamation sign
before it: a != b .
Like all other operators, a comparison returns a value. In this case, the value is a boolean.
true – means “yes”, “correct” or “the truth”.
false – means “no”, “wrong” or “not the truth”.
For example:
A comparison result can be assigned to a variable, just like any value:
To see whether a string is greater than another, JavaScript uses the so-called “dictionary” or “lexicographical”
order.
In other words, strings are compared letter-by-letter.
For example:
The algorithm to compare two strings is simple:
1. Compare the first character of both strings.
2. If the first character from the first string is greater (or less) than the other string’s, then the first string is
greater (or less) than the second. We’re done.
3. Otherwise, if both strings’ first characters are the same, compare the second characters the same way.
4. Repeat until the end of either string.
5. If both strings end at the same length, then they are equal. Otherwise, the longer string is greater.
In the examples above, the comparison 'Z' > 'A' gets to a result at the first step while the strings "Glow"
and "Glee" are compared character-by-character:
1. G is the same as G .
2. l is the same as l .
3. o is greater than e . Stop here. The first string is greater.
Not a real dictionary, but Unicode order
The comparison algorithm given above is roughly equivalent to the one used in dictionaries or phone
books, but it’s not exactly the same.
For instance, case matters. A capital letter "A" is not equal to the lowercase "a" . Which one is greater?
The lowercase "a" . Why? Because the lowercase character has a greater index in the internal encoding
table JavaScript uses (Unicode). We’ll get back to specific details and consequences of this in the chapter
Strings.
When comparing values of different types, JavaScript converts the values to numbers.
For example:
For boolean values, true becomes 1 and false becomes 0 .
For example:
A funny consequence
It is possible that at the same time:
Two values are equal.
One of them is true as a boolean and the other one is false as a boolean.
For example:
From JavaScript’s standpoint, this result is quite normal. An equality check converts values using the
numeric conversion (hence "0" becomes 0 ), while the explicit Boolean conversion uses another set of
rules.
A regular equality check == has a problem. It cannot differentiate 0 from false :
The same thing happens with an empty string:
This happens because operands of different types are converted to numbers by the equality operator == . An
empty string, just like false , becomes a zero.
What to do if we’d like to differentiate 0 from false ?
A strict equality operator === checks the equality without type conversion.
In other words, if a and b are of different types, then a === b immediately returns false without an attempt
to convert them.
Let’s try it:
There is also a “strict non-equality” operator !== analogous to != .
The strict equality operator is a bit longer to write, but makes it obvious what’s going on and leaves less room for
errors.
Let’s see more edge cases.
There’s a non-intuitive behavior when null or undefined are compared to other values.
For a strict equality check ===
These values are different, because each of them is a different type.
For a non-strict check ==
There’s a special rule. These two are a “sweet couple”: they equal each other (in the sense of == ), but not any
other value.
For maths and other comparisons < > <= >=
null/undefined are converted to numbers: null becomes 0 , while undefined becomes NaN .
Now let’s see some funny things that happen when we apply these rules. And, what’s more important, how to not
fall into a trap with them.
Let’s compare null with a zero:
Mathematically, that’s strange. The last result states that " null is greater than or equal to zero", so one of the
comparisons above it must be correct, but they are both false.
The reason is that an equality check == and comparisons > < >= <= work differently. Comparisons convert
null to a number, treating it as 0 . That’s why (3) null >= 0 is true and (1) null > 0 is false.
On the other hand, the equality check == for undefined and null is defined such that, without any
conversions, they equal each other and don’t equal anything else. That’s why (2) null == 0 is false.
The value undefined shouldn’t be compared to other values:
Why does it dislike zero so much? Always false!
We get these results because:
Comparisons (1) and (2) return false because undefined gets converted to NaN and NaN is a special
numeric value which returns false for all comparisons.
The equality check (3) returns false because undefined only equals null and no other value.
Why did we go over these examples? Should we remember these peculiarities all the time? Well, not really.
Actually, these tricky things will gradually become familiar over time, but there’s a solid way to evade problems
with them:
Just treat any comparison with undefined/null except the strict equality === with exceptional care.
Don’t use comparisons >= > < <= with a variable which may be null/undefined , unless you’re really sure of
what you’re doing. If a variable can have these values, check for them separately.
Comparison operators return a boolean value.
Strings are compared letter-by-letter in the “dictionary” order.
When values of different types are compared, they get converted to numbers (with the exclusion of a strict
equality check).
The values null and undefined equal == each other and do not equal any other value.
Be careful when using comparisons like > or < with variables that can occasionally be null/undefined .
Checking for null/undefined separately is a good idea.
importance: 5
What will be the result for these expressions?
solution
Boolean is the result
alert( 2 > 1 ); // true (correct)
alert( 2 == 1 ); // false (wrong)
alert( 2 != 1 ); // true (correct)
1
2
3
let result = 5 > 4; // assign the result of the comparison
alert( result ); // true
1
2
String comparison
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
1
2
3
Comparison of different types
alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1
1
2
alert( true == 1 ); // true
alert( false == 0 ); // true
1
2
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
1
2
3
4
5
6
7
Strict equality
alert( 0 == false ); // true1
alert( '' == false ); // true1
alert( 0 === false ); // false, because the types are different1
Comparison with null and undefined
alert( null === undefined ); // false1
alert( null == undefined ); // true1
Strange result: null vs 0
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
1
2
3
An incomparable undefined
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
1
2
3
Evade problems
Summary
Tasks
Comparisons
5 > 4
"apple" > "pineapple"
"2" > "12"
undefined == null
undefined === null
null == "\n0\n"
null === +"\n0\n"
1
2
3
4
5
6
7
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
Boolean is the result
String comparison
Comparison of different types
Strict equality
Comparison with null and
undefined
Summary
Tasks (1)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Interaction: alert, prompt, confirm
This part of the tutorial aims to cover JavaScript “as is”, without environment-specific tweaks.
But we’ll still be using the browser as our demo environment, so we should know at least a few of its user-
interface functions. In this chapter, we’ll get familiar with the browser functions alert , prompt and confirm .
Syntax:
This shows a message and pauses script execution until the user presses “OK”.
For example:
The mini-window with the message is called a modal window. The word “modal” means that the visitor can’t
interact with the rest of the page, press other buttons, etc. until they have dealt with the window. In this case –
until they press “OK”.
The function prompt accepts two arguments:
It shows a modal window with a text message, an input field for the visitor, and the buttons OK/CANCEL.
title
The text to show the visitor.
default
An optional second parameter, the initial value for the input field.
The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing
CANCEL or hitting the Esc key.
The call to prompt returns the text from the input field or null if the input was canceled.
For instance:
In IE: always supply a default
The second parameter is optional, but if we don’t supply it, Internet Explorer will insert the text
"undefined" into the prompt.
Run this code in Internet Explorer to see:
So, for prompts to look good in IE, we recommend always providing the second argument:
The syntax:
The function confirm shows a modal window with a question and two buttons: OK and CANCEL.
The result is true if OK is pressed and false otherwise.
For example:
We covered 3 browser-specific functions to interact with visitors:
alert
shows a message.
prompt
shows a message asking the user to input text. It returns the text or, if CANCEL or Esc is clicked, null .
confirm
shows a message and waits for the user to press “OK” or “CANCEL”. It returns true for OK and false for
CANCEL/ Esc .
All these methods are modal: they pause script execution and don’t allow the visitor to interact with the rest of
the page until the window has been dismissed.
There are two limitations shared by all the methods above:
1. The exact location of the modal window is determined by the browser. Usually, it’s in the center.
2. The exact look of the window also depends on the browser. We can’t modify it.
That is the price for simplicity. There are other ways to show nicer windows and richer interaction with the visitor,
but if “bells and whistles” do not matter much, these methods work just fine.
importance: 4
Create a web-page that asks for a name and outputs it.
Run the demo
solution
alert
alert(message);1
alert("Hello");1
prompt
result = prompt(title[, default]);1
let age = prompt('How old are you?', 100);
alert(`You are ${age} years old!`); // You are 100 years old!
1
2
3
let test = prompt("Test");1
let test = prompt("Test", ''); // <-- for IE1
confirm
result = confirm(question);1
let isBoss = confirm("Are you the boss?");
alert( isBoss ); // true if OK is pressed
1
2
3
Summary
Tasks
A simple page
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
alert
prompt
confirm
Summary
Tasks (1)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Conditional operators: if, '?'
Sometimes, we need to perform different actions based on different conditions.
To do that, we use the if statement and the conditional (ternary) operator which we will be referring to as the
“question mark” operator ? for simplicity.
The if statement evaluates a condition and, if the condition’s result is true , executes a block of code.
For example:
In the example above, the condition is a simple equality check ( year == 2015 ), but it can be much more
complex.
If we want to execute more than one statement, we have to wrap our code block inside curly braces:
We recommend wrapping your code block with curly braces {} every time you use an if statement, even if
there is only one statement to execute. Doing so improves readability.
The if (…) statement evaluates the expression in its parentheses and converts the result to a boolean.
Let’s recall the conversion rules from the chapter Type Conversions:
A number 0 , an empty string "" , null , undefined , and NaN all become false . Because of that they are
called “falsy” values.
Other values become true , so they are called “truthy”.
So, the code under this condition would never execute:
…and inside this condition – it always will:
We can also pass a pre-evaluated boolean value to if , like this:
The if statement may contain an optional “else” block. It executes when the condition is false.
For example:
Sometimes, we’d like to test several variants of a condition. The else if clause lets us do that.
For example:
In the code above, JavaScript first checks year < 2015 . If that is falsy, it goes to the next condition year >
2015 . If that is also falsy, it shows the last alert .
There can be more else if blocks. The final else is optional.
Sometimes, we need to assign a variable depending on a condition.
For instance:
The so-called “ternary” or “question mark” operator lets us do that in a shorter and simpler way.
The operator is represented by a question mark ? . The formal term “ternary” means that the operator has three
operands. It is actually the one and only operator in JavaScript which has that many.
The syntax is:
The condition is evaluated: if it’s truthy then value1 is returned, otherwise – value2 .
For example:
Technically, we can omit the parentheses around age > 18 . The question mark operator has a low precedence,
so it executes after the comparison > .
This example will do the same thing as the previous one:
But parentheses make the code more readable, so we recommend using them.
Please note:
In the example above, you can avoid using the question mark operator because the comparison itself
returns true/false :
A sequence of question mark operators ? can return a value that depends on more than one condition.
For instance:
It may be difficult at first to grasp what’s going on. But after a closer look, we can see that it’s just an ordinary
sequence of tests:
1. The first question mark checks whether age < 3 .
2. If true – it returns 'Hi, baby!' . Otherwise, it continues to the expression after the colon ‘":"’, checking age
< 18 .
3. If that’s true – it returns 'Hello!' . Otherwise, it continues to the expression after the next colon ‘":"’,
checking age < 100 .
4. If that’s true – it returns 'Greetings!' . Otherwise, it continues to the expression after the last colon ‘":"’,
returning 'What an unusual age!' .
Here’s how this looks using if..else :
Sometimes the question mark ? is used as a replacement for if :
Depending on the condition company == 'Netscape' , either the first or the second expression after the ?
gets executed and shows an alert.
We don’t assign a result to a variable here. Instead, we execute different code depending on the condition.
We don’t recommend using the question mark operator in this way.
The notation is shorter than the equivalent if statement, which appeals to some programmers. But it is less
readable.
Here is the same code using if for comparison:
Our eyes scan the code vertically. Code blocks which span several lines are easier to understand than a long,
horizontal instruction set.
The purpose of the question mark operator ? is to return one value or another depending on its condition.
Please use it for exactly that. Use if when you need to execute different branches of code.
importance: 5
Will alert be shown?
solution
importance: 2
Using the if..else construct, write the code which asks: ‘What is the “official” name of JavaScript?’
If the visitor enters “ECMAScript”, then output “Right!”, otherwise – output: “Didn’t know? ECMAScript!”
Demo in new window
solution
importance: 2
Using if..else , write the code which gets a number via prompt and then shows in alert :
1 , if the value is greater than zero,
-1 , if less than zero,
0 , if equals zero.
In this task we assume that the input is always a number.
Demo in new window
solution
importance: 5
Rewrite this if using the ternary operator '?' :
solution
importance: 5
Rewrite if..else using multiple ternary operators '?' .
For readability, it’s recommended to split the code into multiple lines.
solution
The “if” statement
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
if (year == 2015) alert( 'You are right!' );
1
2
3
if (year == 2015) {
alert( "That's correct!" );
alert( "You're so smart!" );
}
1
2
3
4
Boolean conversion
if (0) { // 0 is falsy
...
}
1
2
3
if (1) { // 1 is truthy
...
}
1
2
3
let cond = (year == 2015); // equality evaluates to true or false
if (cond) {
...
}
1
2
3
4
5
The “else” clause
let year = prompt('In which year was the ECMAScript-2015 specification published?', '');
if (year == 2015) {
alert( 'You guessed it right!' );
} else {
alert( 'How can you be so wrong?' ); // any value except 2015
}
1
2
3
4
5
6
7
Several conditions: “else if”
let year = prompt('In which year was the ECMAScript-2015 specification published?', '');
if (year < 2015) {
alert( 'Too early...' );
} else if (year > 2015) {
alert( 'Too late' );
} else {
alert( 'Exactly!' );
}
1
2
3
4
5
6
7
8
9
Ternary operator ‘?’
let accessAllowed;
let age = prompt('How old are you?', '');
if (age > 18) {
accessAllowed = true;
} else {
accessAllowed = false;
}
alert(accessAllowed);
1
2
3
4
5
6
7
8
9
10
let result = condition ? value1 : value2;1
let accessAllowed = (age > 18) ? true : false;1
// the comparison operator "age > 18" executes first anyway
// (no need to wrap it into parentheses)
let accessAllowed = age > 18 ? true : false;
1
2
3
// the same
let accessAllowed = age > 18;
1
2
Multiple ‘?’
let age = prompt('age?', 18);
let message = (age < 3) ? 'Hi, baby!' :
(age < 18) ? 'Hello!' :
(age < 100) ? 'Greetings!' :
'What an unusual age!';
alert( message );
1
2
3
4
5
6
7
8
if (age < 3) {
message = 'Hi, baby!';
} else if (age < 18) {
message = 'Hello!';
} else if (age < 100) {
message = 'Greetings!';
} else {
message = 'What an unusual age!';
}
1
2
3
4
5
6
7
8
9
Non-traditional use of ‘?’
let company = prompt('Which company created JavaScript?', '');
(company == 'Netscape') ?
alert('Right!') : alert('Wrong.');
1
2
3
4
let company = prompt('Which company created JavaScript?', '');
if (company == 'Netscape') {
alert('Right!');
} else {
alert('Wrong.');
}
1
2
3
4
5
6
7
Tasks
if (a string with zero)
if ("0") {
alert( 'Hello' );
}
1
2
3
The name of JavaScript
Show the sign
Rewrite 'if' into '?'
if (a + b < 4) {
result = 'Below';
} else {
result = 'Over';
}
1
2
3
4
5
Rewrite 'if..else' into '?'
let message;
if (login == 'Employee') {
message = 'Hello';
} else if (login == 'Director') {
message = 'Greetings';
} else if (login == '') {
message = 'No login';
} else {
message = '';
}
1
2
3
4
5
6
7
8
9
10
11
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
The “if” statement
Boolean conversion
The “else” clause
Several conditions: “else if”
Ternary operator ‘?’
Multiple ‘?’
Non-traditional use of ‘?’
Tasks (5)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Logical operators
There are three logical operators in JavaScript: || (OR), && (AND), ! (NOT).
Although they are called “logical”, they can be applied to values of any type, not only boolean. Their result can
also be of any type.
Let’s see the details.
The “OR” operator is represented with two vertical line symbols:
In classical programming, the logical OR is meant to manipulate boolean values only. If any of its arguments are
true , it returns true , otherwise it returns false .
In JavaScript, the operator is a little bit trickier and more powerful. But first, let’s see what happens with boolean
values.
There are four possible logical combinations:
As we can see, the result is always true except for the case when both operands are false .
If an operand is not a boolean, it’s converted to a boolean for the evaluation.
For instance, the number 1 is treated as true , the number 0 as false :
Most of the time, OR || is used in an if statement to test if any of the given conditions is true .
For example:
We can pass more conditions:
The logic described above is somewhat classical. Now, let’s bring in the “extra” features of JavaScript.
The extended algorithm works as follows.
Given multiple OR’ed values:
The OR || operator does the following:
Evaluates operands from left to right.
For each operand, converts it to boolean. If the result is true , stops and returns the original value of that
operand.
If all operands have been evaluated (i.e. all were false ), returns the last operand.
A value is returned in its original form, without the conversion.
In other words, a chain of OR "||" returns the first truthy value or the last one if no such value is found.
For instance:
This leads to some interesting usage compared to a “pure, classical, boolean-only OR”.
1. Getting the first truthy value from a list of variables or expressions.
Imagine we have several variables which can either contain data or be null/undefined . How can we find
the first one with data?
We can use OR || :
If both currentUser and defaultUser were falsy, "unnamed" would be the result.
2. Short-circuit evaluation.
Operands can be not only values, but arbitrary expressions. OR evaluates and tests them from left to right. The
evaluation stops when a truthy value is reached, and the value is returned. This process is called “a short-
circuit evaluation” because it goes as short as possible from left to right.
This is clearly seen when the expression given as the second argument has a side effect like a variable
assignment.
In the example below, x does not get assigned:
If, instead, the first argument is false , || evaluates the second one, thus running the assignment:
An assignment is a simple case. Other side effects can also be involved.
As we can see, such a use case is a "shorter way of doing if ". The first operand is converted to boolean. If it’s
false, the second one is evaluated.
Most of time, it’s better to use a “regular” if to keep the code easy to understand, but sometimes this can be
handy.
The AND operator is represented with two ampersands && :
In classical programming, AND returns true if both operands are truthy and false otherwise:
An example with if :
Just as with OR, any value is allowed as an operand of AND:
Given multiple AND’ed values:
The AND && operator does the following:
Evaluates operands from left to right.
For each operand, converts it to a boolean. If the result is false , stops and returns the original value of that
operand.
If all operands have been evaluated (i.e. all were truthy), returns the last operand.
In other words, AND returns the first falsy value or the last value if none were found.
The rules above are similar to OR. The difference is that AND returns the first falsy value while OR returns the first
truthy one.
Examples:
We can also pass several values in a row. See how the first falsy one is returned:
When all values are truthy, the last value is returned:
Precedence of AND && is higher than OR ||
The precedence of AND && operator is higher than OR || .
So the code a && b || c && d is essentially the same as if the && expressions were in parentheses:
(a && b) || (c && d) .
Just like OR, the AND && operator can sometimes replace if .
For instance:
The action in the right part of && would execute only if the evaluation reaches it. That is, only if (x > 0) is true.
So we basically have an analogue for:
The variant with && appears shorter. But if is more obvious and tends to be a little bit more readable.
So we recommend using every construct for its purpose: use if if we want if and use && if we want AND.
The boolean NOT operator is represented with an exclamation sign ! .
The syntax is pretty simple:
The operator accepts a single argument and does the following:
1. Converts the operand to boolean type: true/false .
2. Returns the inverse value.
For instance:
A double NOT !! is sometimes used for converting a value to boolean type:
That is, the first NOT converts the value to boolean and returns the inverse, and the second NOT inverses it again.
In the end, we have a plain value-to-boolean conversion.
There’s a little more verbose way to do the same thing – a built-in Boolean function:
The precedence of NOT ! is the highest of all logical operators, so it always executes first, before && or || .
importance: 5
What is the code below going to output?
solution
importance: 3
What will the code below output?
solution
importance: 5
What is this code going to show?
solution
importance: 3
What will this code show?
solution
importance: 5
What will the result be?
solution
importance: 3
Write an “if” condition to check that age is between 14 and 90 inclusively.
“Inclusively” means that age can reach the edges 14 or 90 .
solution
importance: 3
Write an if condition to check that age is NOT between 14 and 90 inclusively.
Create two variants: the first one using NOT ! , the second one – without it.
solution
importance: 5
Which of these alert s are going to execute?
What will the results of the expressions be inside if(...) ?
solution
importance: 3
Write the code which asks for a login with prompt .
If the visitor enters "Admin" , then prompt for a password, if the input is an empty line or Esc – show
“Canceled.”, if it’s another string – then show “I don’t know you”.
The password is checked as follows:
If it equals “TheMaster”, then show “Welcome!”,
Another string – show “Wrong password”,
For an empty string or cancelled input, show “Canceled.”
The schema:
Please use nested if blocks. Mind the overall readability of the code.
Hint: passing an empty input to a prompt returns an empty string '' . Pressing ESC during a prompt returns
null .
Run the demo
solution
|| (OR)
result = a || b;1
alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false
1
2
3
4
if (1 || 0) { // works just like if( true || false )
alert( 'truthy!' );
}
1
2
3
let hour = 9;
if (hour < 10 || hour > 18) {
alert( 'The office is closed.' );
}
1
2
3
4
5
let hour = 12;
let isWeekend = true;
if (hour < 10 || hour > 18 || isWeekend) {
alert( 'The office is closed.' ); // it is the weekend
}
1
2
3
4
5
6
OR finds the first truthy value
result = value1 || value2 || value3;1
alert( 1 || 0 ); // 1 (1 is truthy)
alert( true || 'no matter what' ); // (true is truthy)
alert( null || 1 ); // 1 (1 is the first truthy value)
alert( null || 0 || 1 ); // 1 (the first truthy value)
alert( undefined || null || 0 ); // 0 (all falsy, returns the last value)
1
2
3
4
5
6
let currentUser = null;
let defaultUser = "John";
let name = currentUser || defaultUser || "unnamed";
alert( name ); // selects "John" – the first truthy value
1
2
3
4
5
6
let x;
true || (x = 1);
alert(x); // undefined, because (x = 1) not evaluated
1
2
3
4
5
let x;
false || (x = 1);
alert(x); // 1
1
2
3
4
5
&& (AND)
result = a && b;1
alert( true && true ); // true
alert( false && true ); // false
alert( true && false ); // false
alert( false && false ); // false
1
2
3
4
let hour = 12;
let minute = 30;
if (hour == 12 && minute == 30) {
alert( 'The time is 12:30' );
}
1
2
3
4
5
6
if (1 && 0) { // evaluated as true && false
alert( "won't work, because the result is falsy" );
}
1
2
3
AND finds the first falsy value
result = value1 && value2 && value3;1
// if the first operand is truthy,
// AND returns the second operand:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5
// if the first operand is falsy,
// AND returns it. The second operand is ignored
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
1
2
3
4
5
6
7
8
9
alert( 1 && 2 && null && 3 ); // null1
alert( 1 && 2 && 3 ); // 3, the last one1
let x = 1;
(x > 0) && alert( 'Greater than zero!' );
1
2
3
let x = 1;
if (x > 0) {
alert( 'Greater than zero!' );
}
1
2
3
4
5
! (NOT)
result = !value;1
alert( !true ); // false
alert( !0 ); // true
1
2
alert( !!"non-empty string" ); // true
alert( !!null ); // false
1
2
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
1
2
Tasks
What's the result of OR?
alert( null || 2 || undefined );1
What's the result of OR'ed alerts?
alert( alert(1) || 2 || alert(3) );1
What is the result of AND?
alert( 1 && null && 2 );1
What is the result of AND'ed alerts?
alert( alert(1) && alert(2) );1
The result of OR AND OR
alert( null || 2 && 3 || 4 );1
Check the range between
Check the range outside
A question about "if"
if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );
1
2
3
Check the login
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
|| (OR)
OR finds the first truthy value
&& (AND)
AND finds the first falsy value
! (NOT)
Tasks (9)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Loops: while and for
We often need to repeat actions.
For example, outputting goods from a list one after another or just running the same code for each number from
1 to 10.
Loops are a way to repeat the same code multiple times.
The while loop has the following syntax:
While the condition is true , the code from the loop body is executed.
For instance, the loop below outputs i while i < 3 :
A single execution of the loop body is called an iteration. The loop in the example above makes three iterations.
If i++ was missing from the example above, the loop would repeat (in theory) forever. In practice, the browser
provides ways to stop such loops, and in server-side JavaScript, we can kill the process.
Any expression or variable can be a loop condition, not just comparisons: the condition is evaluated and
converted to a boolean by while .
For instance, a shorter way to write while (i != 0) is while (i) :
Brackets are not required for a single-line body
If the loop body has a single statement, we can omit the brackets {…} :
The condition check can be moved below the loop body using the do..while syntax:
The loop will first execute the body, then check the condition, and, while it’s truthy, execute it again and again.
For example:
This form of syntax should only be used when you want the body of the loop to execute at least once regardless
of the condition being truthy. Usually, the other form is preferred: while(…) {…} .
The for loop is the most commonly used loop.
It looks like this:
Let’s learn the meaning of these parts by example. The loop below runs alert(i) for i from 0 up to (but not
including) 3 :
Let’s examine the for statement part-by-part:
part
begin i = 0 Executes once upon entering the loop.
condition i < 3 Checked before every loop iteration. If false, the loop stops.
step i++ Executes after the body on each iteration but before the condition check.
body alert(i) Runs again and again while the condition is truthy.
The general loop algorithm works like this:
If you are new to loops, it could help to go back to the example and reproduce how it runs step-by-step on a
piece of paper.
Here’s exactly what happens in our case:
Inline variable declaration
Here, the “counter” variable i is declared right in the loop. This is called an “inline” variable declaration.
Such variables are visible only inside the loop.
Instead of defining a variable, we could use an existing one:
Any part of for can be skipped.
For example, we can omit begin if we don’t need to do anything at the loop start.
Like here:
We can also remove the step part:
This makes the loop identical to while (i < 3) .
We can actually remove everything, creating an infinite loop:
Please note that the two for semicolons ; must be present. Otherwise, there would be a syntax error.
Normally, a loop exits when its condition becomes falsy.
But we can force the exit at any time using the special break directive.
For example, the loop below asks the user for a series of numbers, “breaking” when no number is entered:
The break directive is activated at the line (*) if the user enters an empty line or cancels the input. It stops the
loop immediately, passing control to the first line after the loop. Namely, alert .
The combination “infinite loop + break as needed” is great for situations when a loop’s condition must be
checked not in the beginning or end of the loop, but in the middle or even in several places of its body.
The continue directive is a “lighter version” of break . It doesn’t stop the whole loop. Instead, it stops the
current iteration and forces the loop to start a new one (if the condition allows).
We can use it if we’re done with the current iteration and would like to move on to the next one.
The loop below uses continue to output only odd values:
For even values of i , the continue directive stops executing the body and passes control to the next iteration
of for (with the next number). So the alert is only called for odd values.
The continue directive helps decrease nesting
A loop that shows odd values could look like this:
From a technical point of view, this is identical to the example above. Surely, we can just wrap the code in
an if block instead of using continue .
But as a side-effect, this created one more level of nesting (the alert call inside the curly braces). If the
code inside of if is longer than a few lines, that may decrease the overall readability.
No break/continue to the right side of ‘?’
Please note that syntax constructs that are not expressions cannot be used with the ternary operator ? .
In particular, directives such as break/continue aren’t allowed there.
For example, if we take this code:
…and rewrite it using a question mark:
…it stops working. Code like this will give a syntax error:
This is just another reason not to use the question mark operator ? instead of if .
Sometimes we need to break out from multiple nested loops at once.
For example, in the code below we loop over i and j , prompting for the coordinates (i, j) from (0,0) to
(3,3) :
We need a way to stop the process if the user cancels the input.
The ordinary break after input would only break the inner loop. That’s not sufficient–labels, come to the
rescue!
A label is an identifier with a colon before a loop:
The break <labelName> statement in the loop below breaks out to the label:
In the code above, break outer looks upwards for the label named outer and breaks out of that loop.
So the control goes straight from (*) to alert('Done!') .
We can also move the label onto a separate line:
The continue directive can also be used with a label. In this case, code execution jumps to the next iteration of
the labeled loop.
Labels are not a “goto”
Labels do not allow us to jump into an arbitrary place in the code.
For example, it is impossible to do this:
A call to break/continue is only possible from inside a loop and the label must be somewhere above
the directive.
We covered 3 types of loops:
while – The condition is checked before each iteration.
do..while – The condition is checked after each iteration.
for (;;) – The condition is checked before each iteration, additional settings available.
To make an “infinite” loop, usually the while(true) construct is used. Such a loop, just like any other, can be
stopped with the break directive.
If we don’t want to do anything in the current iteration and would like to forward to the next one, we can use the
continue directive.
break/continue support labels before the loop. A label is the only way for break/continue to escape a
nested loop to go to an outer one.
importance: 3
What is the last value alerted by this code? Why?
solution
importance: 4
For every loop iteration, write down which value it outputs and then compare it with the solution.
Both loops alert the same values, or not?
1. The prefix form ++i :
2. The postfix form i++
solution
importance: 4
For each loop write down which values it is going to show. Then compare with the answer.
Both loops alert same values or not?
1. The postfix form:
2. The prefix form:
solution
importance: 5
Use the for loop to output even numbers from 2 to 10 .
Run the demo
solution
importance: 5
Rewrite the code changing the for loop to while without altering its behavior (the output should stay same).
solution
importance: 5
Write a loop which prompts for a number greater than 100 . If the visitor enters another number – ask them to
input again.
The loop must ask for a number until either the visitor enters a number greater than 100 or cancels the
input/enters an empty line.
Here we can assume that the visitor only inputs numbers. There’s no need to implement a special handling for a
non-numeric input in this task.
Run the demo
solution
importance: 3
An integer number greater than 1 is called a prime if it cannot be divided without a remainder by anything
except 1 and itself.
In other words, n > 1 is a prime if it can’t be evenly divided by anything except 1 and n .
For example, 5 is a prime, because it cannot be divided without a remainder by 2 , 3 and 4 .
Write the code which outputs prime numbers in the interval from 2 to n .
For n = 10 the result will be 2,3,5,7 .
P.S. The code should work for any n , not be hard-tuned for any fixed value.
solution
The “while” loop
while (condition) {
// code
// so-called "loop body"
}
1
2
3
4
let i = 0;
while (i < 3) { // shows 0, then 1, then 2
alert( i );
i++;
}
1
2
3
4
5
let i = 3;
while (i) { // when i becomes 0, the condition becomes falsy, and the loop stops
alert( i );
i--;
}
1
2
3
4
5
let i = 3;
while (i) alert(i--);
1
2
The “do…while” loop
do {
// loop body
} while (condition);
1
2
3
let i = 0;
do {
alert( i );
i++;
} while (i < 3);
1
2
3
4
5
The “for” loop
for (begin; condition; step) {
// ... loop body ...
}
1
2
3
for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2
alert(i);
}
1
2
3
Run begin
→ (if condition → run body and run step)
→ (if condition → run body and run step)
→ (if condition → run body and run step)
→ ...
1
2
3
4
5
// for (let i = 0; i < 3; i++) alert(i)
// run begin
let i = 0
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// ...finish, because now i == 3
1
2
3
4
5
6
7
8
9
10
11
for (let i = 0; i < 3; i++) {
alert(i); // 0, 1, 2
}
alert(i); // error, no such variable
1
2
3
4
let i = 0;
for (i = 0; i < 3; i++) { // use an existing variable
alert(i); // 0, 1, 2
}
alert(i); // 3, visible, because declared outside of the loop
1
2
3
4
5
6
7
Skipping parts
let i = 0; // we have i already declared and assigned
for (; i < 3; i++) { // no need for "begin"
alert( i ); // 0, 1, 2
}
1
2
3
4
5
let i = 0;
for (; i < 3;) {
alert( i++ );
}
1
2
3
4
5
for (;;) {
// repeats without limits
}
1
2
3
Breaking the loop
let sum = 0;
while (true) {
let value = +prompt("Enter a number", '');
if (!value) break; // (*)
sum += value;
}
alert( 'Sum: ' + sum );
1
2
3
4
5
6
7
8
9
10
11
12
Continue to the next iteration
for (let i = 0; i < 10; i++) {
// if true, skip the remaining part of the body
if (i % 2 == 0) continue;
alert(i); // 1, then 3, 5, 7, 9
}
1
2
3
4
5
6
7
for (let i = 0; i < 10; i++) {
if (i % 2) {
alert( i );
}
}
1
2
3
4
5
6
7
if (i > 5) {
alert(i);
} else {
continue;
}
1
2
3
4
5
(i > 5) ? alert(i) : continue; // continue isn't allowed here1
Labels for break/continue
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let input = prompt(`Value at coords (${i},${j})`, '');
// what if I want to exit from here to Done (below)?
}
}
alert('Done!');
1
2
3
4
5
6
7
8
9
10
11
12
labelName: for (...) {
...
}
1
2
3
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let input = prompt(`Value at coords (${i},${j})`, '');
// if an empty string or canceled, then break out of both loops
if (!input) break outer; // (*)
// do something with the value...
}
}
alert('Done!');
1
2
3
4
5
6
7
8
9
10
11
12
13
outer:
for (let i = 0; i < 3; i++) { ... }
1
2
break label; // jumps to label? No.
label: for (...)
1
2
3
Summary
Tasks
Last loop value
let i = 3;
while (i) {
alert( i-- );
}
1
2
3
4
5
Which values does the while loop show?
let i = 0;
while (++i < 5) alert( i );
1
2
let i = 0;
while (i++ < 5) alert( i );
1
2
Which values get shown by the "for" loop?
for (let i = 0; i < 5; i++) alert( i );1
for (let i = 0; i < 5; ++i) alert( i );1
Output even numbers in the loop
Replace "for" with "while"
for (let i = 0; i < 3; i++) {
alert( `number ${i}!` );
}
1
2
3
Repeat until the input is correct
Output prime numbers
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
The “while” loop
The “do…while” loop
The “for” loop
Breaking the loop
Continue to the next iteration
Labels for break/continue
Summary
Tasks (7)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
The "switch" statement
A switch statement can replace multiple if checks.
It gives a more descriptive way to compare a value with multiple variants.
The switch has one or more case blocks and an optional default.
It looks like this:
The value of x is checked for a strict equality to the value from the first case (that is, value1 ) then to the
second ( value2 ) and so on.
If the equality is found, switch starts to execute the code starting from the corresponding case , until the
nearest break (or until the end of switch ).
If no case is matched then the default code is executed (if it exists).
An example of switch (the executed code is highlighted):
Here the switch starts to compare a from the first case variant that is 3 . The match fails.
Then 4 . That’s a match, so the execution starts from case 4 until the nearest break .
If there is no break then the execution continues with the next case without any checks.
An example without break :
In the example above we’ll see sequential execution of three alert s:
Any expression can be a switch/case argument
Both switch and case allow arbitrary expressions.
For example:
Here +a gives 1 , that’s compared with b + 1 in case , and the corresponding code is executed.
Several variants of case which share the same code can be grouped.
For example, if we want the same code to run for case 3 and case 5 :
Now both 3 and 5 show the same message.
The ability to “group” cases is a side-effect of how switch/case works without break . Here the execution of
case 3 starts from the line (*) and goes through case 5 , because there’s no break .
Let’s emphasize that the equality check is always strict. The values must be of the same type to match.
For example, let’s consider the code:
1. For 0 , 1 , the first alert runs.
2. For 2 the second alert runs.
3. But for 3 , the result of the prompt is a string "3" , which is not strictly equal === to the number 3 . So
we’ve got a dead code in case 3 ! The default variant will execute.
importance: 5
Write the code using if..else which would correspond to the following switch :
solution
importance: 4
Rewrite the code below using a single switch statement:
solution
The syntax
switch(x) {
case 'value1': // if (x === 'value1')
...
[break]
case 'value2': // if (x === 'value2')
...
[break]
default:
...
[break]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
An example
let a = 2 + 2;
switch (a) {
case 3:
alert( 'Too small' );
break;
case 4:
alert( 'Exactly!' );
break;
case 5:
alert( 'Too large' );
break;
default:
alert( "I don't know such values" );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let a = 2 + 2;
switch (a) {
case 3:
alert( 'Too small' );
case 4:
alert( 'Exactly!' );
case 5:
alert( 'Too big' );
default:
alert( "I don't know such values" );
}
1
2
3
4
5
6
7
8
9
10
11
12
alert( 'Exactly!' );
alert( 'Too big' );
alert( "I don't know such values" );
1
2
3
let a = "1";
let b = 0;
switch (+a) {
case b + 1:
alert("this runs, because +a is 1, exactly equals b+1");
break;
default:
alert("this doesn't run");
}
1
2
3
4
5
6
7
8
9
10
11
Grouping of “case”
let a = 2 + 2;
switch (a) {
case 4:
alert('Right!');
break;
case 3: // (*) grouped two cases
case 5:
alert('Wrong!');
alert("Why don't you take a math class?");
break;
default:
alert('The result is strange. Really.');
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Type matters
let arg = prompt("Enter a value?")
switch (arg) {
case '0':
case '1':
alert( 'One or zero' );
break;
case '2':
alert( 'Two' );
break;
case 3:
alert( 'Never executes!' );
break;
default:
alert( 'An unknown value' )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Tasks
Rewrite the "switch" into an "if"
switch (browser) {
case 'Edge':
alert( "You've got the Edge!" );
break;
case 'Chrome':
case 'Firefox':
case 'Safari':
case 'Opera':
alert( 'Okay we support these browsers too' );
break;
default:
alert( 'We hope that this page looks ok!' );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Rewrite "if" into "switch"
let a = +prompt('a?', '');
if (a == 0) {
alert( 0 );
}
if (a == 1) {
alert( 1 );
}
if (a == 2 || a == 3) {
alert( '2,3' );
}
1
2
3
4
5
6
7
8
9
10
11
12
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
The syntax
An example
Grouping of “case”
Type matters
Tasks (2)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Functions
Quite often we need to perform a similar action in many places of the script.
For example, we need to show a nice-looking message when a visitor logs in, logs out and maybe somewhere
else.
Functions are the main “building blocks” of the program. They allow the code to be called many times without
repetition.
We’ve already seen examples of built-in functions, like alert(message) , prompt(message, default) and
confirm(question) . But we can create functions of our own as well.
To create a function we can use a function declaration.
It looks like this:
The function keyword goes first, then goes the name of the function, then a list of parameters between the
parentheses (empty in the example above) and finally the code of the function, also named “the function body”,
between curly braces.
Our new function can be called by its name: showMessage() .
For instance:
The call showMessage() executes the code of the function. Here we will see the message two times.
This example clearly demonstrates one of the main purposes of functions: to avoid code duplication.
If we ever need to change the message or the way it is shown, it’s enough to modify the code in one place: the
function which outputs it.
A variable declared inside a function is only visible inside that function.
For example:
A function can access an outer variable as well, for example:
The function has full access to the outer variable. It can modify it as well.
For instance:
The outer variable is only used if there’s no local one. So an occasional modification may happen if we forget
let .
If a same-named variable is declared inside the function then it shadows the outer one. For instance, in the code
below the function uses the local userName . The outer one is ignored:
Global variables
Variables declared outside of any function, such as the outer userName in the code above, are called
global.
Global variables are visible from any function (unless shadowed by locals).
Usually, a function declares all variables specific to its task. Global variables only store project-level data,
so when it’s important that these variables are accesible from anywhere. Modern code has few or no
globals. Most variables reside in their functions.
We can pass arbitrary data to functions using parameters (also called function arguments) .
In the example below, the function has two parameters: from and text .
When the function is called in lines (*) and (**) , the given values are copied to local variables from and
text . Then the function uses them.
Here’s one more example: we have a variable from and pass it to the function. Please note: the function changes
from , but the change is not seen outside, because a function always gets a copy of the value:
If a parameter is not provided, then its value becomes undefined .
For instance, the aforementioned function showMessage(from, text) can be called with a single argument:
That’s not an error. Such a call would output "Ann: undefined" . There’s no text , so it’s assumed that text
=== undefined .
If we want to use a “default” text in this case, then we can specify it after = :
Now if the text parameter is not passed, it will get the value "no text given"
Here "no text given" is a string, but it can be a more complex expression, which is only evaluated and
assigned if the parameter is missing. So, this is also possible:
Evaluation of default parameters
In JavaScript, a default parameter is evaluated every time the function is called without the respective
parameter. In the example above, anotherFunction() is called every time showMessage() is called
without the text parameter. This is in contrast to some other languages like Python, where any default
parameters are evaluated only once during the initial interpretation.
Default parameters old-style
Old editions of JavaScript did not support default parameters. So there are alternative ways to support
them, that you can find mostly in the old scripts.
For instance, an explicit check for being undefined :
…Or the || operator:
A function can return a value back into the calling code as the result.
The simplest example would be a function that sums two values:
The directive return can be in any place of the function. When the execution reaches it, the function stops, and
the value is returned to the calling code (assigned to result above).
There may be many occurrences of return in a single function. For instance:
It is possible to use return without a value. That causes the function to exit immediately.
For example:
In the code above, if checkAge(age) returns false , then showMovie won’t proceed to the alert .
A function with an empty return or without it returns undefined
If a function does not return a value, it is the same as if it returns undefined :
An empty return is also the same as return undefined :
Never add a newline between return and the value
For a long expression in return , it might be tempting to put it on a separate line, like this:
That doesn’t work, because JavaScript assumes a semicolon after return . That’ll work the same as:
So, it effectively becomes an empty return. We should put the value on the same line instead.
Functions are actions. So their name is usually a verb. It should be brief, as accurate as possible and describe
what the function does, so that someone reading the code gets an indication of what the function does.
It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There must
be an agreement within the team on the meaning of the prefixes.
For instance, functions that start with "show" usually show something.
Function starting with…
"get…" – return a value,
"calc…" – calculate something,
"create…" – create something,
"check…" – check something and return a boolean, etc.
Examples of such names:
With prefixes in place, a glance at a function name gives an understanding what kind of work it does and what
kind of value it returns.
One function – one action
A function should do exactly what is suggested by its name, no more.
Two independent actions usually deserve two functions, even if they are usually called together (in that
case we can make a 3rd function that calls those two).
A few examples of breaking this rule:
getAge – would be bad if it shows an alert with the age (should only get).
createForm – would be bad if it modifies the document, adding a form to it (should only create it
and return).
checkPermission – would be bad if it displays the access granted/denied message (should only
perform the check and return the result).
These examples assume common meanings of prefixes. What they mean for you is determined by you
and your team. Maybe it’s pretty normal for your code to behave differently. But you should have a firm
understanding of what a prefix means, what a prefixed function can and cannot do. All same-prefixed
functions should obey the rules. And the team should share the knowledge.
Ultrashort function names
Functions that are used very often sometimes have ultrashort names.
For example, the jQuery framework defines a function with $ . The LoDash library has its core function
named _ .
These are exceptions. Generally functions names should be concise and descriptive.
Functions should be short and do exactly one thing. If that thing is big, maybe it’s worth it to split the function
into a few smaller functions. Sometimes following this rule may not be that easy, but it’s definitely a good thing.
A separate function is not only easier to test and debug – its very existence is a great comment!
For instance, compare the two functions showPrimes(n) below. Each one outputs prime numbers up to n .
The first variant uses a label:
The second variant uses an additional function isPrime(n) to test for primality:
The second variant is easier to understand, isn’t it? Instead of the code piece we see a name of the action
( isPrime ). Sometimes people refer to such code as self-describing.
So, functions can be created even if we don’t intend to reuse them. They structure the code and make it readable.
A function declaration looks like this:
Values passed to a function as parameters are copied to its local variables.
A function may access outer variables. But it works only from inside out. The code outside of the function
doesn’t see its local variables.
A function can return a value. If it doesn’t, then its result is undefined .
To make the code clean and easy to understand, it’s recommended to use mainly local variables and parameters
in the function, not outer variables.
It is always easier to understand a function which gets parameters, works with them and returns a result than a
function which gets no parameters, but modifies outer variables as a side-effect.
Function naming:
A name should clearly describe what the function does. When we see a function call in the code, a good name
instantly gives us an understanding what it does and returns.
A function is an action, so function names are usually verbal.
There exist many well-known function prefixes like create… , show… , get… , check… and so on. Use them to
hint what a function does.
Functions are the main building blocks of scripts. Now we’ve covered the basics, so we actually can start creating
and using them. But that’s only the beginning of the path. We are going to return to them many times, going
more deeply into their advanced features.
importance: 4
The following function returns true if the parameter age is greater than 18 .
Otherwise it asks for a confirmation and returns its result:
Will the function work differently if else is removed?
Is there any difference in the behavior of these two variants?
solution
importance: 4
The following function returns true if the parameter age is greater than 18 .
Otherwise it asks for a confirmation and returns its result.
Rewrite it, to perform the same, but without if , in a single line.
Make two variants of checkAge :
1. Using a question mark operator ?
2. Using OR ||
solution
importance: 1
Write a function min(a,b) which returns the least of two numbers a and b .
For instance:
solution
importance: 4
Write a function pow(x,n) that returns x in power n . Or, in other words, multiplies x by itself n times and
returns the result.
Create a web-page that prompts for x and n , and then shows the result of pow(x,n) .
Run the demo
P.S. In this task the function should support only natural values of n : integers up from 1 .
solution
Function Declaration
function showMessage() {
alert( 'Hello everyone!' );
}
1
2
3
function showMessage() {
alert( 'Hello everyone!' );
}
showMessage();
showMessage();
1
2
3
4
5
6
Local variables
function showMessage() {
let message = "Hello, I'm JavaScript!"; // local variable
alert( message );
}
showMessage(); // Hello, I'm JavaScript!
alert( message ); // <-- Error! The variable is local to the function
1
2
3
4
5
6
7
8
9
Outer variables
let userName = 'John';
function showMessage() {
let message = 'Hello, ' + userName;
alert(message);
}
showMessage(); // Hello, John
1
2
3
4
5
6
7
8
let userName = 'John';
function showMessage() {
userName = "Bob"; // (1) changed the outer variable
let message = 'Hello, ' + userName;
alert(message);
}
alert( userName ); // John before the function call
showMessage();
alert( userName ); // Bob, the value was modified by the function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let userName = 'John';
function showMessage() {
let userName = "Bob"; // declare a local variable
let message = 'Hello, ' + userName; // Bob
alert(message);
}
// the function will create and use its own userName
showMessage();
alert( userName ); // John, unchanged, the function did not access the outer variable
1
2
3
4
5
6
7
8
9
10
11
12
13
Parameters
function showMessage(from, text) { // arguments: from, text
alert(from + ': ' + text);
}
showMessage('Ann', 'Hello!'); // Ann: Hello! (*)
showMessage('Ann', "What's up?"); // Ann: What's up? (**)
1
2
3
4
5
6
function showMessage(from, text) {
from = '*' + from + '*'; // make "from" look nicer
alert( from + ': ' + text );
}
let from = "Ann";
showMessage(from, "Hello"); // *Ann*: Hello
// the value of "from" is the same, the function modified a local copy
alert( from ); // Ann
1
2
3
4
5
6
7
8
9
10
11
12
13
Default values
showMessage("Ann");1
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
1
2
3
4
5
function showMessage(from, text = anotherFunction()) {
// anotherFunction() only executed if no text given
// its result becomes the value of text
}
1
2
3
4
function showMessage(from, text) {
if (text === undefined) {
text = 'no text given';
}
alert( from + ": " + text );
}
1
2
3
4
5
6
7
function showMessage(from, text) {
// if text is falsy then text gets the "default" value
text = text || 'no text given';
...
}
1
2
3
4
5
Returning a value
function sum(a, b) {
return a + b;
}
let result = sum(1, 2);
alert( result ); // 3
1
2
3
4
5
6
function checkAge(age) {
if (age > 18) {
return true;
} else {
return confirm('Do you have permission from your parents?');
}
}
let age = prompt('How old are you?', 18);
if ( checkAge(age) ) {
alert( 'Access granted' );
} else {
alert( 'Access denied' );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function showMovie(age) {
if ( !checkAge(age) ) {
return;
}
alert( "Showing you the movie" ); // (*)
// ...
}
1
2
3
4
5
6
7
8
function doNothing() { /* empty */ }
alert( doNothing() === undefined ); // true
1
2
3
function doNothing() {
return;
}
alert( doNothing() === undefined ); // true
1
2
3
4
5
return
(some + long + expression + or + whatever * f(a) + f(b))
1
2
return;
(some + long + expression + or + whatever * f(a) + f(b))
1
2
Naming a function
showMessage(..) // shows a message
getAge(..) // returns the age (gets it somehow)
calcSum(..) // calculates a sum and returns the result
createForm(..) // creates a form (and usually returns it)
checkPermission(..) // checks a permission, returns true/false
1
2
3
4
5
Functions == Comments
function showPrimes(n) {
nextPrime: for (let i = 2; i < n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert( i ); // a prime
}
}
1
2
3
4
5
6
7
8
9
10
function showPrimes(n) {
for (let i = 2; i < n; i++) {
if (!isPrime(i)) continue;
alert(i); // a prime
}
}
function isPrime(n) {
for (let i = 2; i < n; i++) {
if ( n % i == 0) return false;
}
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Summary
function name(parameters, delimited, by, comma) {
/* code */
}
1
2
3
Tasks
Is "else" required?
function checkAge(age) {
if (age > 18) {
return true;
} else {
// ...
return confirm('Did parents allow you?');
}
}
1
2
3
4
5
6
7
8
function checkAge(age) {
if (age > 18) {
return true;
}
// ...
return confirm('Did parents allow you?');
}
1
2
3
4
5
6
7
Rewrite the function using '?' or '||'
function checkAge(age) {
if (age > 18) {
return true;
} else {
return confirm('Do you have your parents permission to access this page?');
}
}
1
2
3
4
5
6
7
Function min(a, b)
min(2, 5) == 2
min(3, -1) == -1
min(1, 1) == 1
1
2
3
Function pow(x,n)
pow(3, 2) = 3 * 3 = 9
pow(3, 3) = 3 * 3 * 3 = 27
pow(1, 100) = 1 * 1 * ...* 1 = 1
1
2
3
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
Function Declaration
Local variables
Outer variables
Parameters
Default values
Returning a value
Naming a function
Functions == Comments
Summary
Tasks (4)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
Function expressions and arrows
In JavaScript, a function is not a “magical language structure”, but a special kind of value.
The syntax that we used before is called a Function Declaration:
There is another syntax for creating a function that is called a Function Expression.
It looks like this:
Here, the function is created and assigned to the variable explicitly, like any other value. No matter how the
function is defined, it’s just a value stored in the variable sayHi .
The meaning of these code samples is the same: "create a function and put it into the variable sayHi ".
We can even print out that value using alert :
Please note that the last line does not run the function, because there are no parentheses after sayHi . There are
programming languages where any mention of a function name causes its execution, but JavaScript is not like
that.
In JavaScript, a function is a value, so we can deal with it as a value. The code above shows its string
representation, which is the source code.
It is a special value of course, in the sense that we can call it like sayHi() .
But it’s still a value. So we can work with it like with other kinds of values.
We can copy a function to another variable:
Here’s what happens above in detail:
1. The Function Declaration (1) creates the function and puts it into the variable named sayHi .
2. Line (2) copies it into the variable func .
Please note again: there are no parentheses after sayHi . If there were, then func = sayHi() would write
the result of the call sayHi() into func , not the function sayHi itself.
3. Now the function can be called as both sayHi() and func() .
Note that we could also have used a Function Expression to declare sayHi , in the first line:
Everything would work the same. Even more obvious what’s going on, right?
Why is there a semicolon at the end?
You might wonder, why does Function Expression have a semicolon ; at the end, but Function
Declaration does not:
The answer is simple:
There’s no need for ; at the end of code blocks and syntax structures that use them like if { ...
} , for { } , function f { } etc.
A Function Expression is used inside the statement: let sayHi = ...; , as a value. It’s not a code
block. The semicolon ; is recommended at the end of statements, no matter what is the value. So the
semicolon here is not related to the Function Expression itself in any way, it just terminates the
statement.
Let’s look at more examples of passing functions as values and using function expressions.
We’ll write a function ask(question, yes, no) with three parameters:
question
Text of the question
yes
Function to run if the answer is “Yes”
no
Function to run if the answer is “No”
The function should ask the question and, depending on the user’s answer, call yes() or no() :
Before we explore how we can write it in a much shorter way, let’s note that in the browser (and on the server-
side in some cases) such functions are quite popular. The major difference between a real-life implementation
and the example above is that real-life functions use more complex ways to interact with the user than a simple
confirm . In the browser, such a function usually draws a nice-looking question window. But that’s another story.
The arguments of ask are called callback functions or just callbacks.
The idea is that we pass a function and expect it to be “called back” later if necessary. In our case, showOk
becomes the callback for the “yes” answer, and showCancel for the “no” answer.
We can use Function Expressions to write the same function much shorter:
Here, functions are declared right inside the ask(...) call. They have no name, and so are called anonymous.
Such functions are not accessible outside of ask (because they are not assigned to variables), but that’s just
what we want here.
Such code appears in our scripts very naturally, it’s in the spirit of JavaScript.
A function is a value representing an “action”
Regular values like strings or numbers represent the data.
A function can be perceived as an action.
We can pass it between variables and run when we want.
Let’s formulate the key differences between Function Declarations and Expressions.
First, the syntax: how to see what is what in the code.
Function Declaration: a function, declared as a separate statement, in the main code flow.
Function Expression: a function, created inside an expression or inside another syntax construct. Here, the
function is created at the right side of the “assignment expression” = :
The more subtle difference is when a function is created by the JavaScript engine.
A Function Expression is created when the execution reaches it and is usable from then on.
Once the execution flow passes to the right side of the assignment let sum = function… – here we go, the
function is created and can be used (assigned, called, etc. ) from now on.
Function Declarations are different.
A Function Declaration is usable in the whole script/code block.
In other words, when JavaScript prepares to run the script or a code block, it first looks for Function Declarations
in it and creates the functions. We can think of it as an “initialization stage”.
And after all of the Function Declarations are processed, the execution goes on.
As a result, a function declared as a Function Declaration can be called earlier than it is defined.
For example, this works:
The Function Declaration sayHi is created when JavaScript is preparing to start the script and is visible
everywhere in it.
…If it was a Function Expression, then it wouldn’t work:
Function Expressions are created when the execution reaches them. That would happen only in the line (*) . Too
late.
When a Function Declaration is made within a code block, it is visible everywhere inside that block. But
not outside of it.
Sometimes that’s handy to declare a local function only needed in that block alone. But that feature may also
cause problems.
For instance, let’s imagine that we need to declare a function welcome() depending on the age variable that
we get during runtime. And then we plan to use it some time later.
The code below doesn’t work:
That’s because a Function Declaration is only visible inside the code block in which it resides.
Here’s another example:
What can we do to make welcome visible outside of if ?
The correct approach would be to use a Function Expression and assign welcome to the variable that is declared
outside of if and has the proper visibility.
Now it works as intended:
Or we could simplify it even further using a question mark operator ? :
When should you choose Function Declaration versus Function Expression?
As a rule of thumb, when we need to declare a function, the first to consider is Function Declaration
syntax, the one we used before. It gives more freedom in how to organize our code, because we can call
such functions before they are declared.
It’s also a little bit easier to look up function f(…) {…} in the code than let f = function(…) {…} .
Function Declarations are more “eye-catching”.
…But if a Function Declaration does not suit us for some reason (we’ve seen an example above), then
Function Expression should be used.
There’s one more very simple and concise syntax for creating functions, that’s often better than Function
Expressions. It’s called “arrow functions”, because it looks like this:
…This creates a function func that has arguments arg1..argN , evaluates the expression on the right side
with their use and returns its result.
In other words, it’s roughly the same as:
…But much more concise.
Let’s see an example:
If we have only one argument, then parentheses can be omitted, making that even shorter:
If there are no arguments, parentheses should be empty (but they should be present):
Arrow functions can be used in the same way as Function Expressions.
For instance, here’s the rewritten example with welcome() :
Arrow functions may appear unfamiliar and not very readable at first, but that quickly changes as the eyes get
used to the structure.
They are very convenient for simple one-line actions, when we’re just too lazy to write many words.
Multiline arrow functions
The examples above took arguments from the left of => and evaluated the right-side expression with
them.
Sometimes we need something a little bit more complex, like multiple expressions or statements. It is also
possible, but we should enclose them in curly braces. Then use a normal return within them.
Like this:
More to come
Here we praised arrow functions for brevity. But that’s not all! Arrow functions have other interesting
features. We’ll return to them later in the chapter Arrow functions revisited.
For now, we can already use them for one-line actions and callbacks.
Functions are values. They can be assigned, copied or declared in any place of the code.
If the function is declared as a separate statement in the main code flow, that’s called a “Function Declaration”.
If the function is created as a part of an expression, it’s called a “Function Expression”.
Function Declarations are processed before the code block is executed. They are visible everywhere in the
block.
Function Expressions are created when the execution flow reaches them.
In most cases when we need to declare a function, a Function Declaration is preferable, because it is visible prior
to the declaration itself. That gives us more flexibility in code organization, and is usually more readable.
So we should use a Function Expression only when a Function Declaration is not fit for the task. We’ve seen a
couple of examples of that in this chapter, and will see more in the future.
Arrow functions are handy for one-liners. They come in two flavors:
1. Without curly braces: (...args) => expression – the right side is an expression: the function evaluates it
and returns the result.
2. With curly braces: (...args) => { body } – brackets allow us to write multiple statements inside the
function, but we need an explicit return to return something.
Replace Function Expressions with arrow functions in the code:
solution
function sayHi() {
alert( "Hello" );
}
1
2
3
let sayHi = function() {
alert( "Hello" );
};
1
2
3
function sayHi() {
alert( "Hello" );
}
alert( sayHi ); // shows the function code
1
2
3
4
5
function sayHi() { // (1) create
alert( "Hello" );
}
let func = sayHi; // (2) copy
func(); // Hello // (3) run the copy (it works)!
sayHi(); // Hello // this still works too (why wouldn't it)
1
2
3
4
5
6
7
8
let sayHi = function() { ... };
let func = sayHi;
// ...
1
2
3
4
function sayHi() {
// ...
}
let sayHi = function() {
// ...
};
1
2
3
4
5
6
7
Callback functions
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "You agreed." );
}
function showCancel() {
alert( "You canceled the execution." );
}
// usage: functions showOk, showCancel are passed as arguments to ask
ask("Do you agree?", showOk, showCancel);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
ask(
"Do you agree?",
function() { alert("You agreed."); },
function() { alert("You canceled the execution."); }
);
1
2
3
4
5
6
7
8
9
10
Function Expression vs Function Declaration
// Function Declaration
function sum(a, b) {
return a + b;
}
1
2
3
4
// Function Expression
let sum = function(a, b) {
return a + b;
};
1
2
3
4
sayHi("John"); // Hello, John
function sayHi(name) {
alert( `Hello, ${name}` );
}
1
2
3
4
5
sayHi("John"); // error!
let sayHi = function(name) { // (*) no magic any more
alert( `Hello, ${name}` );
};
1
2
3
4
5
let age = prompt("What is your age?", 18);
// conditionally declare a function
if (age < 18) {
function welcome() {
alert("Hello!");
}
} else {
function welcome() {
alert("Greetings!");
}
}
// ...use it later
welcome(); // Error: welcome is not defined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let age = 16; // take 16 as an example
if (age < 18) {
welcome(); // \ (runs)
// |
function welcome() { // |
alert("Hello!"); // | Function Declaration is available
} // | everywhere in the block where it's declared
// |
welcome(); // / (runs)
} else {
function welcome() { // for age = 16, this "welcome" is never created
alert("Greetings!");
}
}
// Here we're out of curly braces,
// so we can not see Function Declarations made inside of them.
welcome(); // Error: welcome is not defined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let age = prompt("What is your age?", 18);
let welcome;
if (age < 18) {
welcome = function() {
alert("Hello!");
};
} else {
welcome = function() {
alert("Greetings!");
};
}
welcome(); // ok now
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let age = prompt("What is your age?", 18);
let welcome = (age < 18) ?
function() { alert("Hello!"); } :
function() { alert("Greetings!"); };
welcome(); // ok now
1
2
3
4
5
6
7
Arrow functions
let func = (arg1, arg2, ...argN) => expression1
let func = function(arg1, arg2, ...argN) {
return expression;
};
1
2
3
let sum = (a, b) => a + b;
/* The arrow function is a shorter form of:
let sum = function(a, b) {
return a + b;
};
*/
alert( sum(1, 2) ); // 3
1
2
3
4
5
6
7
8
9
10
// same as
// let double = function(n) { return n * 2 }
let double = n => n * 2;
alert( double(3) ); // 6
1
2
3
4
5
let sayHi = () => alert("Hello!");
sayHi();
1
2
3
let age = prompt("What is your age?", 18);
let welcome = (age < 18) ?
() => alert('Hello') :
() => alert("Greetings!");
welcome(); // ok now
1
2
3
4
5
6
7
let sum = (a, b) => { // the curly brace opens a multiline function
let result = a + b;
return result; // if we use curly braces, use return to get results
};
alert( sum(1, 2) ); // 3
1
2
3
4
5
6
Summary
Tasks
Rewrite with arrow functions
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
ask(
"Do you agree?",
function() { alert("You agreed."); },
function() { alert("You canceled the execution."); }
);
1
2
3
4
5
6
7
8
9
10
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
Callback functions
Function Expression vs
Function Declaration
Arrow functions
Summary
Tasks (1)
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language JavaScript Fundamentals
JavaScript specials
This chapter briefly recaps the features of JavaScript that we’ve learned by now, paying special attention to subtle
moments.
Statements are delimited with a semicolon:
Usually, a line-break is also treated as a delimiter, so that would also work:
That’s called “automatic semicolon insertion”. Sometimes it doesn’t work, for instance:
Most codestyle guides agree that we should put a semicolon after each statement.
Semicolons are not required after code blocks {...} and syntax constructs with them like loops:
…But even if we can put an “extra” semicolon somewhere, that’s not an error. It will be ignored.
More in: Code structure.
To fully enable all features of modern JavaScript, we should start scripts with "use strict" .
The directive must be at the top of a script or at the beginning of a function.
Without "use strict" , everything still works, but some features behave in the old-fashion, “compatible” way.
We’d generally prefer the modern behavior.
Some modern features of the language (like classes that we’ll study in the future) enable strict mode implicitly.
More in: The modern mode, "use strict".
Can be declared using:
let
const (constant, can’t be changed)
var (old-style, will see later)
A variable name can include:
Letters and digits, but the first character may not be a digit.
Characters $ and _ are normal, on par with letters.
Non-Latin alphabets and hieroglyphs are also allowed, but commonly not used.
Variables are dynamically typed. They can store any value:
There are 7 data types:
number for both floating-point and integer numbers,
string for strings,
boolean for logical values: true/false ,
null – a type with a single value null , meaning “empty” or “does not exist”,
undefined – a type with a single value undefined , meaning “not assigned”,
object and symbol – for complex data structures and unique identifiers, we haven’t learnt them yet.
The typeof operator returns the type for a value, with two exceptions:
More in: Variables and Data types.
We’re using a browser as a working environment, so basic UI functions will be:
prompt(question[, default])
Ask a question , and return either what the visitor entered or null if they pressed “cancel”.
confirm(question)
Ask a question and suggest to choose between Ok and Cancel. The choice is returned as true/false .
alert(message)
Output a message .
All these functions are modal, they pause the code execution and prevent the visitor from interacting with the
page until they answer.
For instance:
More in: Interaction: alert, prompt, confirm.
JavaScript supports the following operators:
Arithmetical
Regular: * + - / , also % for the remainder and ** for power of a number.
The binary plus + concatenates strings. And if any of the operands is a string, the other one is converted to
string too:
Assignments
There is a simple assignment: a = b and combined ones like a *= 2 .
Bitwise
Bitwise operators work with integers on bit-level: see the docs when they are needed.
Ternary
The only operator with three parameters: cond ? resultA : resultB . If cond is truthy, returns resultA ,
otherwise resultB .
Logical operators
Logical AND && and OR || perform short-circuit evaluation and then return the value where it stopped. Logical
NOT ! converts the operand to boolean type and returns the inverse value.
Comparisons
Equality check == for values of different types converts them to a number (except null and undefined that
equal each other and nothing else), so these are equal:
Other comparisons convert to a number as well.
The strict equality operator === doesn’t do the conversion: different types always mean different values for it, so:
Values null and undefined are special: they equal == each other and don’t equal anything else.
Greater/less comparisons compare strings character-by-character, other types are converted to a number.
Other operators
There are few others, like a comma operator.
More in: Operators, Comparisons, Logical operators.
We covered 3 types of loops:
The variable declared in for(let...) loop is visible only inside the loop. But we can also omit let and
reuse an existing variable.
Directives break/continue allow to exit the whole loop/current iteration. Use labels to break nested loops.
Details in: Loops: while and for.
Later we’ll study more types of loops to deal with objects.
The “switch” construct can replace multiple if checks. It uses === (strict equality) for comparisons.
For instance:
Details in: The "switch" statement.
We covered three ways to create a function in JavaScript:
1. Function Declaration: the function in the main code flow
2. Function Expression: the function in the context of an expression
Function expressions can have a name, like sum = function name(a, b) , but that name is only visible
inside that function.
3. Arrow functions:
Functions may have local variables: those declared inside its body. Such variables are only visible inside the
function.
Parameters can have default values: function sum(a = 1, b = 2) {...} .
Functions always return something. If there’s no return statement, then the result is undefined .
Function Declaration Function Expression
visible in the whole code block created when the execution reaches it
- can have a name, visible only inside the function
More: see Functions, Function expressions and arrows.
That was a brief list of JavaScript features. As of now we’ve studied only basics. Further in the tutorial you’ll find
more specials and advanced features of JavaScript.
Code structure
alert('Hello'); alert('World');1
alert('Hello')
alert('World')
1
2
alert("There will be an error after this message")
[1, 2].forEach(alert)
1
2
3
function f() {
// no semicolon needed after function declaration
}
for(;;) {
// no semicolon needed after the loop
}
1
2
3
4
5
6
7
Strict mode
'use strict';
...
1
2
3
Variables
let x = 5;
x = "John";
1
2
typeof null == "object" // error in the language
typeof function(){} == "function" // functions are treated specially
1
2
Interaction
let userName = prompt("Your name?", "Alice");
let isTeaWanted = confirm("Do you want some tea?");
alert( "Visitor: " + userName ); // Alice
alert( "Tea wanted: " + isTeaWanted ); // true
1
2
3
4
5
Operators
alert( '1' + 2 ); // '12', string
alert( 1 + '2' ); // '12', string
1
2
alert( 0 == false ); // true
alert( 0 == '' ); // true
1
2
Loops
// 1
while (condition) {
...
}
// 2
do {
...
} while (condition);
// 3
for(let i = 0; i < 10; i++) {
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
The “switch” construct
let age = prompt('Your age?', 18);
switch (age) {
case 18:
alert("Won't work"); // the result of prompt is a string, not a number
case "18":
alert("This works!");
break;
default:
alert("Any value not equal to one above");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
Functions
function sum(a, b) {
let result = a + b;
return result;
}
1
2
3
4
5
let sum = function(a, b) {
let result = a + b;
return result;
}
1
2
3
4
5
// expression at the right side
let sum = (a, b) => a + b;
// or multi-line syntax with { ... }, need return here:
let sum = (a, b) => {
// ...
return a + b;
}
// without arguments
let sayHi = () => alert("Hello");
// with a single argument
let double = n => n * 2;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
More to come
Comments
!
Chapter
JavaScript Fundamentals
Lesson navigation
Code structure
Strict mode
Variables
Interaction
Operators
Loops
The “switch” construct
Functions
More to come
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF
The JavaScript language Code quality
Debugging in Chrome
Before writing more complex code, let’s talk about debugging.
All modern browsers and most other environments support “debugging” – a special UI in developer tools that
makes finding and fixing errors much easier.
We’ll be using Chrome here, because it’s probably the most feature-rich in this aspect.
Your Chrome version may look a little bit different, but it still should be obvious what’s there.
Open the example page in Chrome.
Turn on developer tools with F12 (Mac: Cmd+Opt+I ).
Select the sources pane.
Here’s what you should see if you are doing it for the first time:
The toggler button opens the tab with files.
Let’s click it and select index.html and then hello.js in the tree view. Here’s what should show up:
Here we can see three zones:
1. The Resources zone lists HTML, JavaScript, CSS and other files, including images that are attached to the
page. Chrome extensions may appear here too.
2. The Source zone shows the source code.
3. The Information and control zone is for debugging, we’ll explore it soon.
Now you could click the same toggler again to hide the resources list and give the code some space.
If we press Esc , then a console opens below. We can type commands there and press Enter to execute.
After a statement is executed, its result is shown below.
For example, here 1+2 results in 3 , and hello("debugger") returns nothing, so the result is undefined :
Let’s examine what’s going on within the code of the example page. In hello.js , click at line number 4 . Yes,
right on the 4 digit, not on the code.
Congratulations! You’ve set a breakpoint. Please also click on the number for line 8 .
It should look like this (blue is where you should click):
A breakpoint is a point of code where the debugger will automatically pause the JavaScript execution.
While the code is paused, we can examine current variables, execute commands in the console etc. In other
words, we can debug it.
We can always find a list of breakpoints in the right pane. That’s useful when we have many breakpoints in
various files. It allows us to:
Quickly jump to the breakpoint in the code (by clicking on it in the right pane).
Temporarily disable the breakpoint by unchecking it.
Remove the breakpoint by right-clicking and selecting Remove.
…And so on.
Conditional breakpoints
Right click on the line number allows to create a conditional breakpoint. It only triggers when the given
expression is truthy.
That’s handy when we need to stop only for a certain variable value or for certain function parameters.
We can also pause the code by using the debugger command, like this:
That’s very convenient when we are in a code editor and don’t want to switch to the browser and look up the
script in developer tools to set the breakpoint.
In our example, hello() is called during the page load, so the easiest way to activate the debugger is to reload
the page. So let’s press F5 (Windows, Linux) or Cmd+R (Mac).
As the breakpoint is set, the execution pauses at the 4th line:
Please open the informational dropdowns to the right (labeled with arrows). They allow you to examine the
current code state:
1. Watch – shows current values for any expressions.
You can click the plus + and input an expression. The debugger will show its value at any moment,
automatically recalculating it in the process of execution.
2. Call Stack – shows the nested calls chain.
At the current moment the debugger is inside hello() call, called by a script in index.html (no function
there, so it’s called “anonymous”).
If you click on a stack item, the debugger jumps to the corresponding code, and all its variables can be
examined as well.
3. Scope – current variables.
Local shows local function variables. You can also see their values highlighted right over the source.
Global has global variables (out of any functions).
There’s also this keyword there that we didn’t study yet, but we’ll do that soon.
Now it’s time to trace the script.
There are buttons for it at the top of the right pane. Let’s engage them.
– continue the execution, hotkey F8 .
Resumes the execution. If there are no additional breakpoints, then the execution just continues and the
debugger loses control.
Here’s what we can see after a click on it:
The execution has resumed, reached another breakpoint inside say() and paused there. Take a look at the “Call
stack” at the right. It has increased by one more call. We’re inside say() now.
– make a step (run the next command), but don’t go into the function, hotkey F10 .
If we click it now, alert will be shown. The important thing is that alert can be any function, the execution
“steps over it”, skipping the function internals.
– make a step, hotkey F11 .
The same as the previous one, but “steps into” nested functions. Clicking this will step through all script actions
one by one.
– continue the execution till the end of the current function, hotkey Shift+F11 .
The execution would stop at the very last line of the current function. That’s handy when we accidentally entered
a nested call using , but it does not interest us, and we want to continue to its end as soon as possible.
– enable/disable all breakpoints.
That button does not move the execution. Just a mass on/off for breakpoints.
– enable/disable automatic pause in case of an error.
When enabled, and the developer tools is open, a script error automatically pauses the execution. Then we can
analyze variables to see what went wrong. So if our script dies with an error, we can open debugger, enable this
option and reload the page to see where it dies and what’s the context at that moment.
Continue to here
Right click on a line of code opens the context menu with a great option called “Continue to here”.
That’s handy when we want to move multiple steps forward, but we’re too lazy to set a breakpoint.
To output something to console, there’s console.log function.
For instance, this outputs values from 0 to 4 to console:
Regular users don’t see that output, it is in the console. To see it, either open the Console tab of developer tools
or press Esc while in another tab: that opens the console at the bottom.
If we have enough logging in our code, then we can see what’s going on from the records, without the debugger.
As we can see, there are three main ways to pause a script:
1. A breakpoint.
2. The debugger statements.
3. An error (if dev tools are open and the button is “on”).
Then we can examine variables and step on to see where the execution goes wrong.
There are many more options in developer tools than covered here. The full manual is at
https://developers.google.com/web/tools/chrome-devtools.
The information from this chapter is enough to begin debugging, but later, especially if you do a lot of browser
stuff, please go there and look through more advanced capabilities of developer tools.
Oh, and also you can click at various places of dev tools and just see what’s showing up. That’s probably the
fastest route to learn dev tools. Don’t forget about the right click as well!
The “sources” pane
Console
Breakpoints
Debugger command
function hello(name) {
let phrase = `Hello, ${name}!`;
debugger; // <-- the debugger stops here
say(phrase);
}
1
2
3
4
5
6
7
Pause and look around
Tracing the execution
Logging
// open console to see
for (let i = 0; i < 5; i++) {
console.log("value", i);
}
1
2
3
4
Summary
Comments
!
Chapter
Code quality
Lesson navigation
The “sources” pane
Console
Breakpoints
Debugger command
Pause and look around
Tracing the execution
Logging
Summary
Comments
Share
Edit on Github
read this before commenting…
©2007—2019 Ilya Kantor | contact us | terms of usage | privacy policy | about the project
open source
EN
Tutorial Courses
👤
The tutorial was recently rewritten from scratch. There may be typos, please use the "Edit on Github" link (in left sidebar in an article, at the bottom) to propose fixes. Thank you!
Buy EPUB/PDF